- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
I think I found a bug when porting my Windows .dll project to Linux .so. I was working on a dll project (in Visual Studio), and the time came to compile this project on Linux. The project consists of module procedures encapsulated in separate submodules. I found the following issue when compiling this project:
In my VS project, for each module procedure I use !DEC$ ATTRIBUTES DLLEXPORT to make them available outside the world. According to Steve (https://software.intel.com/en-us/forums/intel-fortran-compiler-for-linux-and-mac-os-x/topic/533785?language=en-us&https=1) ifort under Linux should ignore DLLEXPORT. But.. It does not. Here is the example (module + module procedure in a submodule) of what happens:
MODULE MOD1 IMPLICIT NONE INTERFACE MODULE SUBROUTINE PR_MOD1(SOME_INT) IMPLICIT NONE !DEC$ ATTRIBUTES DLLEXPORT :: PR_MOD1 INTEGER, INTENT(IN) :: SOME_INT ! ... END SUBROUTINE PR_MOD1 END INTERFACE END MODULE MOD1
SUBMODULE (MOD1) MOD1_PR_MOD1 IMPLICIT NONE CONTAINS MODULE SUBROUTINE PR_MOD1(SOME_INT) !DEC$ ATTRIBUTES DLLEXPORT, ALIAS:"PR_MOD1" :: PR_MOD1 IMPLICIT NONE INTEGER, INTENT(IN) :: SOME_INT PRINT*, 'PR_MOD1 subroutine issued with an argument: ', SOME_INT END SUBROUTINE PR_MOD1 END SUBMODULE MOD1_PR_MOD1
Compiling above module + submodule into libtest.so library and reviewing it through nm I received:
$ nm -D libtest.so 0000000000000710 T PR_MOD1 w _Jv_RegisterClasses 0000000000200b40 A __bss_start w __cxa_finalize w __gmon_start__ 0000000000200b40 A _edata 0000000000200b50 A _end 00000000000007b8 T _fini 00000000000005c8 T _init U for_write_seq_lis U for_write_seq_lis_xmit 00000000000006f0 T mod1._ 0000000000000700 T mod1.mod1_pr_mod1._
Which means I do not have an access to module subroutine: PR_MOD2. I found that when I modify my DLLEXPORT statement to be handled by the preprocessor, I can avoid this. In this case I will have in module MOD1 (instead of !DEC$ ATTRIBUTES DLLEXPORT :: PR_MOD1):
!DEC$ IF DEFINED(__linux) !DEC$ ELSE !DEC$ ATTRIBUTES DLLEXPORT :: PR_MOD1 !DEC$ ENDIF
and in submodule (instead of !DEC$ ATTRIBUTES DLLEXPORT, ALIAS:"PR_MOD1" :: PR_MOD1):
!DEC$ IF DEFINED(__linux) !DEC$ ELSE !DEC$ ATTRIBUTES DLLEXPORT, ALIAS:"PR_MOD1" :: PR_MOD1 !DEC$ ENDIF
Reviewing libtest.so through nm I received:
w _Jv_RegisterClasses 0000000000200b50 A __bss_start w __cxa_finalize w __gmon_start__ 0000000000200b50 A _edata 0000000000200b60 A _end 00000000000007c8 T _fini 00000000000005d0 T _init U for_write_seq_lis U for_write_seq_lis_xmit 0000000000000700 T mod1._ 0000000000000710 T mod1.mod1_pr_mod1._ 0000000000000720 T mod1_mp_pr_mod1_
Which is different than what it was before. Now, I have module procedure mod1_mp_pr_mod1_ available to use. Please tell me if this is a bug or I am doing sth wrong with placing DLLEXPORT statements in my code.
Regards,
Piotr
P.S. I am using Intel Fortran Compiler 17 Update 1
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
This statement has two directives in it:
!DEC$ ATTRIBUTES DLLEXPORT, ALIAS:"PR_MOD1" :: PR_MOD1
One is the DLLEXPORT, and that is ignored on Linux.
The other is the "ALIAS" and that is *not* ignored on Linux.
Moreover - we should have given an error because the interface and actual declaration don't match, I'll share that with the team.
Does this help?
--Lorri
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I captured the lack of the error for the interface name mismatch that Lorri noted in our internal tracking system.
(Internal tracking id: DPD200416289)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Lorri,
Now, I have to come back to Windows, since what you proposed does not work on Windows.. When I have the same interfaces with ALIAS included :
MODULE MOD1 IMPLICIT NONE INTERFACE MODULE SUBROUTINE PR_MOD1(SOME_INT) !DEC$ ATTRIBUTES DLLEXPORT, ALIAS:"PR_MOD1" :: PR_MOD1 IMPLICIT NONE INTEGER, INTENT(IN) :: SOME_INT ! ... END SUBROUTINE PR_MOD1 END INTERFACE END MODULE MOD1
SUBMODULE (MOD1) MOD1_PR_MOD1 IMPLICIT NONE CONTAINS MODULE SUBROUTINE PR_MOD1(SOME_INT) !DEC$ ATTRIBUTES DLLEXPORT, ALIAS:"PR_MOD1" :: PR_MOD1 IMPLICIT NONE INTEGER, INTENT(IN) :: SOME_INT PRINT*, 'PR_MOD1 subroutine issued with argument: ', SOME_INT END SUBROUTINE PR_MOD1 END SUBMODULE MOD1_PR_MOD1
I am receiving the following compilation error :
Error 1 error #7286: This symbol has multiply declared DEC$ ATTRIBUTES ALIAS attribute. [PR_MOD1] D:\Users\502437587\Documents\Piotr_Gorecki\Projects\OPEN\Fritos\temp\main_app\PR_MOD1.f90 9
Resigning from ALIAS and keeping just:
!DEC$ ATTRIBUTES DLLEXPORT :: PR_MOD1
in both module and submodule, it compiles the code to dll. But when I try to use this DLL in different FORTRAN code:
program Exe4dll !DEC$ ATTRIBUTES DLLIMPORT:: PR_MOD1 implicit none ! Variables call PR_MOD1(11_4) end program Exe4dll
I am receiving the following error:
Error 1 error LNK2019: unresolved external symbol __imp_PR_MOD1 referenced in function MAIN__ Exe4dll.obj Error 2 fatal error LNK1120: 1 unresolved externals x64\Release\Exe4dll.exe
The code from the original post works on Windows. With your suggestions it stops working on Windows.. Am I doing something wrong here? I need to answer this question before we skip to Linux issue.
Thank you,
Piotr
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Piotr -
OK, I just played with this for a bit.
First, I still contend that we should be checking the ALIAS clauses, and I agree that it should NOT give an error in your modified case. I'll add this note to the internal tracking issue that Kevin created.
That said, I finally realized that you needed the alias because you were not using modules to declare the external name. Is there a reason for that? You could simplify this by simply putting DLLEXPORT on the module procedures without the ALIAS clause, and replacing the DLLIMPORT line with USE MOD1
If you do need to give an explicit name, then let me suggest you revert to the original format, and insert the Windows vs Linux conditional compilation until we can correct these 'alias' issues.
Does this help?
--Lorri
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Lorri,
Your solution is fine for me. Originally, I did not want to enforce users of my .dll to use modules. But.. If my original approach is supposed to be incorrect I am totally fine with your idea of using modules to declare the external name.
I tested the code on Windows and Linux (without ALIAS clauses and conditional compilation) and in both cases it works.
Thanks,
Piotr
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page