- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
When I rebuild my code using Visual Fortran Composer XE 2013 SP1 Update 4, previously working (using version 13.0.1.119) imports of variables that are exported from a DLL (created in ObjectAda, if that matters) no longer work. Imports of procedures still work, although it seems that I no longer need to include a DLLIMPORT directive for this.
Here's the code:
real(kind=8) :: DLLFunc
real(kind=8) :: LocalDouble
!DEC$ ATTRIBUTES DLLIMPORT:: DLLFunc
!DEC$ ATTRIBUTES DLLIMPORT:: DLLProc
!DEC$ ATTRIBUTES DLLIMPORT:: LocalDouble
When I rebuild using XE 2013 SP1 Update 4, I can access DLLFunc (a function) and DLLProc (a subroutine) just fine (although it also works now when I leave out the DLLIMPORT directives). However, I get the following compilation error for the imported variable LocalDouble:
error #6406: Conflicting attributes or multiple declaration of name. [LOCALDOUBLE]
I'd appreciate any thoughts regarding what I need to update to get this back in working order, and perhaps some information regarding what changes have been made to compiler support of DLLIMPORT.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I'm not aware of any changes made in this area. Would you please put together a small example, for the DLL and the importer, that shows the problem? How are the variables defined in the DLL - are they in a module or something else? Showing just a snippet of code is not sufficient to understand the issue.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I have attached a Fortran main program (adaTest.f90) and the source used to generate the Ada DLL I'm using for the test (hello.txt; had to change the extension from .ada to get it to allow me to attach the file.)
The DLL function (DLLFunc), procedure (DLLProc), and variable (LocalDouble) are all declared in the Ada package "P" and exported using pragma Export.
Once again, I can successfully call DLLFunc and DLLProc from program adaTest, but now the Fortran import directive
!DEC$ ATTRIBUTES DLLIMPORT:: LocalDouble
gives me an error 6406 during compilation.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The variable LocalDouble is declared to be real(KIND=8), initialized with a value in that declaration, and is then declared later as DLLIMPORT via a directive. These conflicting declarations are what the compiler is complaining about. Even the Compaq 6.6c Fortran compiler gives a corresponding error message for adaTest.f90. If you remove the initialization, the error message will go away.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
If I remove the initialization of LocalDouble, error #6406 goes away. However, I still get a link error:
error LNK2019: unresolved external symbol LOCALDOUBLE referenced in function _MAIN__
Just to clarify: If I build this code using VFC XE 13.0.1.119, I get no link error and proper import of the DLL variable LOCALDOUBLE.
If I build it using VFC XE 14.0.4.237, I get the link error.
In both cases, the imports of DLLFunc and DLLProc work correctly.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I doubt that there are many forum readers who use Ada, but here is a link that may help with sharing data between a DLL and an EXE: https://software.intel.com/en-us/comment/reply/286496/1513030 . I assume that the Ada DLL contains a shared .DATA segment, which would be the case if the DLL was linked with the linker option /section:.DATA,RWS. You also need to declare the shared data in a Fortran module and link that along with the import library for the DLL when you build your Fortran program. It may help to use the following Fortran DLL code to work and then try to get the Ada DLL to work. File adadll.f90:
module shared_glob !ada dll simulated in Fortran double precision :: SharedDouble=acos(-1d0) !DEC$ Attributes DLLExport :: SharedDouble end module subroutine DLLProc() !DEC$ Attributes DLLExport :: DLLProc write(*,*)'In DLLProc()' return end subroutine function DLLFunc(x) result (y) !DEC$ Attributes DLLExport :: DLLFunc double precision :: x,y y=x*x write(*,*)'In DLLFunc ',x,y return end function
We build the DLL and import library using the command
ifort /LD adadll.f90 /link /section:.data,RWS
Here is a simplified version of the client program, adatest.f90:
program adaTest use shared_glob ! declares shared data implicit none ! Import Ada DLL procedures real(kind=8) :: DLLFunc !DEC$ ATTRIBUTES DLLIMPORT:: DLLFunc !DEC$ ATTRIBUTES DLLIMPORT:: DLLProc ! Locals integer :: out_int = 5 integer :: in_int integer(kind=2) :: local_int_2 = 6 real(kind=8) :: out_double = 12.345678910111213_8 real(kind=8) :: in_double, in_double_func call DLLProc() write(*,'(1x,"shareddouble: ",/)') write(*,*) shareddouble in_double_func = DLLFunc(out_double) write(*,'(1x,"Back In FortDrive: ",/)') write(6,1006) in_double_func 1006 format(1x,"Double input from Ada function: ", F18.15) end program adaTest
We build the EXE using the command:
ifort adaTest.f90 adadll.lib
We can then run and test the EXE for working correctly.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Your original code is in error, as noted by mecej4. You should not be DLLIMPORTing a symbol that is initialized.
I suggest you run your Ada DLL through DependencyWalker and see what the name is of the symbol it exports.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I used DependencyWalker to confirm that the Ada DLL export name is LOCALDOUBLE, the same as I have in my Fortran DLLIMPORT.
As I said in my last post, the test code that I sent you (adaTest.f90, with the initialization correction) compiles, links and runs correctly (including import of LOCALDOUBLE from the Ada DLL) when I use VFC XE 13.0.1.119. However, if I build it using VFC XE 14.0.4.237, I get the link error
error LNK2019: unresolved external symbol LOCALDOUBLE referenced in function _MAIN__.
This would seem to imply that a change in Composer XE is causing the difficulty.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
What are you linking against? Please provide the .lib file from the Ada DLL.
Even if there was a change, it was to fix a bug as your original code is incorrect.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks - an interesting problem. I'll let you know what I find.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Here is a slight modification of the file adatest.f90 in #10, which builds and runs fine with IFort 15.0.1.
Browsing the Fortran Standard yielded the following extract:
15.3 Interoperation with C global variables
2 A C variable with external linkage may interoperate with a common block or with a variable declared
3 in the scope of a module. The common block or variable shall be specified to have the BIND attribute.
It is likely that the requirement that the global variable be in a module was not enforced in the older version of the compiler because many Fortran 2003 features had not yet been implemented in that compiler.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The suggested code modification got rid of the link error, but the import of LOCALDOUBLE from the Ada DLL still does not work. (The value of LOCALDOUBLE is still 1234.5 after return from the call to DLLProc.) Note that this same behavior was seen for both compiler versions (13.0.1.119 and 14.0.4.237).
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
My knowledge of Ada dates from the 1980s, well before things like this pragma. I do know that sharing data from a DLL requires a special form of export and it is not clear to me that the pragma in the Ada code is doing this - maybe it is. It would be useful to create a Fortran version of the Ada DLL - something just to verify that the data is being properly referenced - and see if the behavior is different.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I did as you suggested and created a simple Fortran DLL that exports a subroutine and a variable (please see attached files). When building main.f90, I get the link error
error LNK2001: unresolved external symbol __imp_FDLL_DOUBLE
If I comment out the FDLL_DOUBLE DLLIMPORT statement in main, the code builds and accesses the imported subroutine FDLL just fine.
Am I doing something wrong with the Fortran DLL data export/import?
Regarding the Ada DLL: I keep coming back to the facts that 1) the procedure export/import works fine, and 2) the data export/import also works fine when I build with the previous version of Fortran Composer XE.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Because you put the variable in a module, by default its external name has the module name as well.
But yes, there indeed seems to be a bug here. The DLLIMPORT of the variable isn't referencing the import name, which should be __imp__FDLL_DOUBLE, and yes, 13.1 did it right. Looks like we broke this in 14.0. I also looked at various ways to work around the problem, using ALIAS and other things, but wasn't able to find one. I will report this to the developers and let you know of progress or if we find a workaround.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
OK, thanks very much!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I posted too soon - I found a workaround.
Create a separate source file with contents as follows:
module mystuff real(8), bind(C,NAME="LOCALDOUBLE") :: LocalDouble !DEC$ ATTRIBUTES DLLIMPORT :: LocalDouble end module mystuff
You can change the name of "mystuff" to be whatever you want. Add a "use mystuff" in the program or routine where you want to use LocalDouble.
In your Ada code, change the external name of LocalDouble to be "_LOCALDOUBLE" with the underscore - this is what it should be. I wasn't able to find a way to preserve the name without the leading underscore and have everything else work.
Add the module source to your Fortran build, making sure it compiles first (if you do this in a VS project, it will.) This should all now work correctly.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Steve,
This worked for both compiler versions and should allow me to press ahead. Thanks again for your help.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I'm glad I was able to find the workaround. Escalated as issue DPD200366023.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
This has been fixed for a release later this year.

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page