Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

!DEC$ ATTRIBUTES DLLEXPORT is not ignored when porting Windows .dll project to Linux .so

Piotr_G_1
Beginner
1,103 Views

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

0 Kudos
5 Replies
Lorri_M_Intel
Employee
1,103 Views

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

0 Kudos
Kevin_D_Intel
Employee
1,103 Views

I captured the lack of the error for the interface name mismatch that Lorri noted in our internal tracking system.

(Internal tracking id: DPD200416289)

0 Kudos
Piotr_G_1
Beginner
1,103 Views

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

0 Kudos
Lorri_M_Intel
Employee
1,103 Views

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

 

 

 

 

0 Kudos
Piotr_G_1
Beginner
1,103 Views

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

0 Kudos
Reply