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

SUBMODULE/STDCALL/BIND(C)/Unresolved external

andrew_4619
Honored Contributor II
1,017 Views
!  subm_link_prob.f90   
module mymod
    use ifwin
    implicit none
    INTERFACE
        MODULE FUNCTION FRED(HDLG) BIND(C,NAME='FRED')
            !DEC$ ATTRIBUTES STDCALL :: FRED
            INTEGER(INT_PTR)                   :: FRED
            INTEGER(HANDLE),INTENT(IN), VALUE  :: HDLG
        END FUNCTION FRED
    END INTERFACE
end module mymod
    
submodule (mymod) mymod_subs
    implicit none
    contains
    module function FRED( hDlg) BIND(C,NAME='FRED')
        implicit none
        integer(INT_PTR)                    :: FRED
        integer(HANDLE), intent(in), VALUE  :: hDlg       
        FRED = 1_INT_PTR
    end function FRED
end submodule mymod_subs

program subm_link_prob
    use ifwin
    use mymod
    implicit none
    integer (INT_PTR) :: iret
    print *, 'Hello World'
    iret = FRED(0_handle)
    print *, iret
end program subm_link_prob

1>------ Build started: Project: subm_link_prob, Configuration: Debug Win32 ------
1>Compiling with Intel(R) Visual Fortran Compiler 16.0 [IA-32]...
1>subm_link_prob.f90
1>Linking...
1>subm_link_prob.obj : error LNK2019: unresolved external symbol _FRED@4 referenced in function _MAIN__
1>Debug\subm_link_prob.exe : fatal error LNK1120: 1 unresolved externals

What is the problem?

0 Kudos
31 Replies
FortranFan
Honored Contributor II
735 Views

Hmm.. not sure, the following snipped without STDCALL doesn't work either:

module m

   implicit none

   interface
      module subroutine sm_sub() bind(C, name="sm_sub")
      end subroutine sm_sub
   end interface

contains

   subroutine sub() bind(C, name="sub")
      print *, "sub: Hello World!"
      return
   end subroutine sub

end module m
submodule(m) sm

contains

   module subroutine sm_sub() bind(C, name="sm_sub")
      print *, "sm_sub: Hello World!"
      return
   end subroutine sm_sub

end submodule sm
program p

   use m, only : sub, sm_sub

   implicit none

   !call sub()    !.. This obviously works
   call sm_sub()

   stop

end program p

 

0 Kudos
FortranFan
Honored Contributor II
735 Views

For whatever it's worth for friends at Intel, dropping the name= specifier as shown in the following works:

module m

   implicit none

   interface
      module subroutine sm_sub() bind(C)
      end subroutine sm_sub
   end interface

end module m
submodule(m) sm

contains

   module subroutine sm_sub() bind(C)
      print *, "sm_sub: Hello World!"
      return
   end subroutine sm_sub

end submodule sm
program p

   use m, only : sm_sub

   implicit none

   call sm_sub()

   stop

end program p
 sm_sub: Hello World!
Press any key to continue . . .

 

0 Kudos
andrew_4619
Honored Contributor II
735 Views

Calling a bind(c) routine from the Fortran side in a sub-module worked in 16 and update 1 but not update 2. No standards warnings either so something is not right....

0 Kudos
Steven_L_Intel1
Employee
735 Views

We'll take a look. I have a faint memory of a standards issue here.

0 Kudos
FortranFan
Honored Contributor II
735 Views

Looks like an IA-32 issue.  The code in the original post works with Intel 64.

0 Kudos
Steven_L_Intel1
Employee
735 Views

Well, I would expect that - STDCALL has no effect on Intel 64 for BIND(C) routines.

0 Kudos
FortranFan
Honored Contributor II
735 Views

Steve Lionel (Intel) wrote:

Well, I would expect that - STDCALL has no effect on Intel 64 for BIND(C) routines.

Steve,

It's possible the need to support STDCALL for IA-32 configuration is behind the issue, but as alluded to in Message #2, one does not need STDCALL to necessarily raise the same error:

module m

   implicit none

   interface
      module subroutine sm_sub() bind(C, name="sm_sub")
      end subroutine sm_sub
   end interface

end module m
submodule(m) sm

contains

   module subroutine sm_sub() bind(C, name="sm_sub")
      print *, "sm_sub: Hello World!"
      return
   end subroutine sm_sub

end submodule sm
program p

   use m, only : sm_sub

   implicit none

   call sm_sub()

   stop

end program p
>ifort f.f90
Intel(R) Visual Fortran Compiler for applications running on IA-32, Version 16.0
.2.180 Build 20160204
Copyright (C) 1985-2016 Intel Corporation.  All rights reserved.

Microsoft (R) Incremental Linker Version 12.00.40629.0
Copyright (C) Microsoft Corporation.  All rights reserved.

-out:f.exe
-subsystem:console
f.obj
f.obj : error LNK2019: unresolved external symbol _sm_sub referenced in function
 _MAIN__
f.exe : fatal error LNK1120: 1 unresolved externals

>ifort f.f90
Intel(R) Visual Fortran Intel(R) 64 Compiler for applications running on Intel(R
) 64, Version 16.0.2.180 Build 20160204
Copyright (C) 1985-2016 Intel Corporation.  All rights reserved.

Microsoft (R) Incremental Linker Version 12.00.40629.0
Copyright (C) Microsoft Corporation.  All rights reserved.

-out:f.exe
-subsystem:console
f.obj

>f
 sm_sub: Hello World!

 

0 Kudos
Lorri_M_Intel
Employee
735 Views

It's possible the need to support STDCALL for IA-32 configuration is behind the issue, but as alluded to in Message #2, one does not need STDCALL to necessarily raise the same error:

It looks like we're getting confused about decorating the name, whether it be for STDCALL or for the Win32 convention of prepending the underscore.

Thanks for the small reproducer -

            --Lorri

 

 

0 Kudos
Steven_L_Intel1
Employee
735 Views

I can't get this to work in Update 1 - are you sure?

Another workaround is to use "module procedure" in the submodule rather than repeating the full declaration.

Escalated as issue DPD200382120.

0 Kudos
andrew_4619
Honored Contributor II
735 Views

Actually I am not 100% sure about update 1 that was from memory,  it would have worked in 16 through because the error was in a sub-module project I know I could build and run at that level.

0 Kudos
andrew_4619
Honored Contributor II
735 Views

thanks,

Steve Lionel (Intel) wrote:
Another workaround is to use "module procedure" in the submodule rather than repeating the full declaration.

I only have one or two API callback routines so I think there are several workarounds that could be used when I pick this project up next. In general I much prefer the "full declaration" form because you can see what you are dealing with all in one place.  Also I wrote a module parser to create interfaces and that is the way I chose it to work  as it is the minimum modification to the existing code.

 

0 Kudos
Steven_L_Intel1
Employee
735 Views

Understood - just pointing out an additional workaround. There are pros and cons to using "module procedure".

0 Kudos
andrew_4619
Honored Contributor II
735 Views

This issue still seems to exist in 16 update 3. I did note a slight variation on this problem this week. If a routine in a submodule calls a bind(C) routine that is in the same submodule it will link OK if that routine is in a different submodule (of the same parent) it will be unresolved.

I also suspect this might relate to the unsatisfied dependencies problem I have in https://software.intel.com/en-us/forums/intel-visual-fortran-compiler-for-windows/topic/629350 

 

 

0 Kudos
Steven_L_Intel1
Employee
735 Views

The linking issue is unrelated to the build dependency issue. The linking problem isn't fixed yet.

0 Kudos
andrew_4619
Honored Contributor II
735 Views

It would appear there is no compiler complaint if the name in BIND(C, name= does not match between the interface and the definition of the procedure for submodules. We get an error with everything else e.g. mismatched, types, kinds, intent etc. but not this. 

Also, I know it is a none standard feature but if we have !DEC$ ATTRIBUTES STDCALL (for example) in the interface the compiler throws and error of we repeat this in the actual routine.

0 Kudos
Steven_L_Intel1
Employee
735 Views

The STDCALL issue is escalated as DPD200411145. MODULE PROCEDURE is a workaround.

The standard doesn't require consistency in the binding label, since it is not a "procedure characteristic", though I wonder if it should. Of course if you make these inconsistent your program won't link. I've asked those on the J3 email list for their thoughts.  I would not want compilers to try to enforce binding label consistency in general, but maybe submodules are a special case.

0 Kudos
andrew_4619
Honored Contributor II
735 Views

Steve Lionel (Intel) wrote:

 Of course if you make these inconsistent your program won't link. 

The program won't link even in they are consistent because of DPD200382120 so I can't ascertain if your statement is correct. If it is a callback routine for an API it will link and run OK so long as the name in the interface is correct leading me to believe the name in the procedure is just ignored by the compiler. Even if the standard does not demand consistency a remark or warning about mismatch would be more user friendly I think. That said one would assume that the interface name would always take priority but where the names are inconsistent what should be compiler behavior be if there is nothing in the standard?

 

 

 

 

0 Kudos
FortranFan
Honored Contributor II
735 Views

andrew_4619 wrote:

.. I also suspect this might relate to the unsatisfied dependencies problem I have in https://software.intel.com/en-us/forums/intel-visual-fortran-compiler-fo... 

I would go out on a limb and suggest the "unsatisfied dependencies problem" is really something external to Intel Fortran and its integration with Visual Studio.  Since you bring it up in this thread too and indicate the "unsatisfied" nature of it, you may want to make a note the ball lies entirely in your court to illustrate the problem, preferably with a reproducer i.e., the onus is totally on you.  I only point this out because I'm quite interested in submodules and I feel I have a vested interest in successful implementation of it in Intel Fortran and using it with Visual Studio.  But with compiler 16 update 3 (or 2) or with compiler 17 beta, I fail to understand the dependency problem you face and I'm curious about the root cause.  Thanks,

0 Kudos
andrew_4619
Honored Contributor II
735 Views

FortranFan wrote:
you may want to make a note the ball lies entirely in your court to illustrate the problem, preferably with a reproducer i.e., the onus is totally on you.  

I agree with that. I had been whittling down a sub-module moving routines a few at a time from a  sub-module with "hidden"  dependencies to a sibling that is OK. This secondary topic was  something that cropped up on route. I though this would allow me to home in on the problem to make a small reproducer but interdependencies created by bind(c) (if  a submodule routine calls a bind(c) routine then they must be in the same submodule otherwise the program cannot link) have made the route not so easy.

 

 

 

0 Kudos
Steven_L_Intel1
Employee
684 Views

I agree that a compiler warning would be friendly. Or maybe even an error message (my preference here). The name given in the module is what users of the module would see.

Still hoping for a test case for the build dependency issue.

0 Kudos
Reply