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

Fortran calling C++ stdcall DLL

PeterTheRascal
Beginner
3,994 Views

Why can I link my Intel Fortran  dll (sum_if.dll)  to my Fortran (sum_test)  but not my C++ one (sum_cpp.dll)?     All are accepted as STDCAL DLLs by other software e.g. Excel VBA (in the attached .zip)

Fortran Linking to sum_if  works with any of:

  1. Linker | Input |  Additional Dependecies= sum_if.lib
  2. Adding.lib to project (e.g. sum_if.lib)
  3. Project Dependencies = sum_if

But for sum_cpp the dll is not found or accepted   i.e.

sum_test.obj : error LNK2019: unresolved external symbol __imp_sum referenced in function _MAIN__

Dependency Walker  shows function=sum on both. So hopefully it is not a "Decoration" issue?

I have attached the VS Community 2013 Solution, as I hope/ expect  the answer is hidden there. 

1. VS 2013 Solution= sumdll  Projects: = Win32

All sharing same ..\Output\Release and Debug directories.  The excel “double check”  lives in Debug. This helps simplify and clarify "finding" the DLL (I wanted to avoid full paths) 

1.1 Sum_if.dll contains:

function sum(a,b)
IMPLICIT NONE
  ! Expose subroutine ExcelDLL to users of this DLL
  !DEC$ATTRIBUTES STDCALL, DLLEXPORT, ALIAS: 'sum'	:: sum
  !DEC$ATTRIBUTES Value :: a,b 
  ! Variables
  integer*4 a,b,sum
  ! Body of ExcelDLL
  sum=a+b
end function sum

1.2 Sum_cpp.dll 

//  Sum_cpp.cpp contains:
int _stdcall sum(int x, int y){
	return x+y;
}

// Sum_cpp.def contains:
LIBRARY	"sum_cpp""
	EXPORTS sum @

1.3 Sum_test

   Interface
      function sum(a,b) 
        IMPLICIT NONE
        ! Expose subroutine ExcelDLL to users of this DLL
        !DEC$ ATTRIBUTES DLLIMPORT, ALIAS:'sum'	:: sum
        !DEC$ATTRIBUTES Value :: a,b
        ! Variables
        INTEGER*4 a,b,sum
      end function sum 
    End Interface
     
    INTEGER*4  :: a_i4b, b_i4b, c_i4b,d_i4b, I, j
    print *, 'add integers'
    a_i4b=7
    b_i4b=43
    c_i4b=sum(a_i4b,b_i4b)
    write(*,'(I10,A,I10,A,I10)')  a_i4b," + ", b_i4b," = ",c_i4b 
    end program vf_dll_test

2. Excel VBA Declares

' all work fine:
' C++
Declare Function sumcpp Lib "sum_cpp.dll" Alias "sum" (ByVal i As Long, ByVal j As Long) As Long

' Intel Fortran 10.1
Declare Function sumif Lib "sum_if.dll" Alias "sum" (ByVal a As Long, ByVal b As Long) As Long
 

Peter

 

0 Kudos
1 Solution
mecej4
Honored Contributor III
3,994 Views

For what it is worth, here is a complete zip of the source files and a batch file to produce a  DLL and an EXE that uses the DLL. Open an IFort - 32 bit command window, and run the batch file.

s:\lang\sumdll\sum_cpp\tst>bld

s:\lang\sumdll\sum_cpp\tst>lib /def:sum_cpp.def /machine:i386
Microsoft (R) Library Manager Version 12.00.31101.0
Copyright (C) Microsoft Corporation.  All rights reserved.

   Creating library sum_cpp.lib and object sum_cpp.exp

s:\lang\sumdll\sum_cpp\tst>icl /LD sum_cpp.cpp sum_cpp.exp
Intel(R) C++ Compiler XE for applications running on IA-32, Version 15.0.4.221 Build 20150407
Copyright (C) 1985-2015 Intel Corporation.  All rights reserved.

sum_cpp.cpp
Microsoft (R) Incremental Linker Version 12.00.31101.0
Copyright (C) Microsoft Corporation.  All rights reserved.

-out:sum_cpp.dll
-dll
-implib:sum_cpp.lib
sum_cpp.obj
sum_cpp.exp

s:\lang\sumdll\sum_cpp\tst>ifort sum_test.f90 sum_cpp.lib
Intel(R) Visual Fortran Compiler XE for applications running on IA-32, Version 15.0.4.221 Build 20150407
Copyright (C) 1985-2015 Intel Corporation.  All rights reserved.

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

-out:sum_test.exe
-subsystem:console
-incremental:no
sum_test.obj
sum_cpp.lib

s:\lang\sumdll\sum_cpp\tst>sum_test
 add integers
         7 +         43 =         50

 

View solution in original post

0 Kudos
14 Replies
mecej4
Honored Contributor III
3,994 Views

You will get the C++ name decoration, which will not link correctly with Fortran, unless you surround the declaration of the extern function in C++ with

     extern "C" {

     ...

     }

Since, in the Fortran part, you used ALIAS, you have suppressed the usual @nnn decoration that comes with STDCALL, so you will have to provide suitable aliases on the C/C++ side as well.

Note also that you have provided an incorrect interface block in sum_test.f90. You should add the stdcall attribute to the imported symbol. Without that, your program will build with no error messages but the EXE will probably crash with access errors, particularly if optimizations are enabled during compilation.

0 Kudos
PeterTheRascal
Beginner
3,994 Views

Thanks Mecej4

My apologies and thanks: I had eliminated the STDCALL as an experiment and, yes, it does crash after running. Now fixed.

Are you suggesting..?

extern "C" {
	  int _stdcall sum(int x, int y){
		  return x + y;
	  }
}

It did not seem to make a difference. As I said, both DLLs seem undecorated ("sum") in Dependency Walker. So should I still pursue your suggestion further?

Attached is the Release directory in full , inc .dll, lib.  (without extern "c" mod)

Sumtest.exe will look for sum_if.dll. But, with appropriate copying and renaming, will run OK with "sum_cpp.dll.  It looks to me like the answer lies in the "sum_cpp.lib" file?

 

 

0 Kudos
mecej4
Honored Contributor III
3,994 Views

Each language compiler/linker package has its own ways of naming external symbols and calling conventions. I do not use VBA or Excel, so I will not comment about what they require, but those are well-documented. There would be less confusion if you defined your objectives precisely instead of attempting some of the many possible combinations.

The dumpbin utility is very helpful in ascertaining the decorated name present in the OBJ, DLL and EXE files. 

0 Kudos
PeterTheRascal
Beginner
3,994 Views

Hi Mecej4

It is never easy summarizing questions clearly. But I am pleased with mine: i.e.

>>Why can I link my Intel Fortran  dll (sum_if.dll)  to my Fortran (sum_test)  but not my C++ one (sum_cpp.dll)?     All are accepted as STDCALL DLLs by other software e.g. Excel VBA (in the attached .zip)

I choose STDCALL throughout.  Some others may have found it useful to demonstrate that both DLLs worked fine in Excel. Though  I later pointed (in my last email) out that the DLL can be run with the fortran with suitable name changing.

Can anyone else please help? As you may guess, my real problem is less trivial but cannot be continued until I crack this.

 

0 Kudos
Steven_L_Intel1
Employee
3,994 Views

Your C++ routine will have an external name of _sum@8. You need to use the appropriate C++ pragma to change that to "sum". I don't know what that would be offhand.

0 Kudos
PeterTheRascal
Beginner
3,994 Views

Steve

Before I study daunting #pragma stuff..:

If Dependency Walker shows "sum" [and no mangling] and the DLL works as "sum" in Excel, Mathematica and even Fortran (exe but not linking) is this really a name mangling issue?

0 Kudos
Steven_L_Intel1
Employee
3,994 Views

Yes. Dependency Walker will lie about things like this.  Do a "dumpbin -exports" on the export library and see what you get.

0 Kudos
mecej4
Honored Contributor III
3,995 Views

For what it is worth, here is a complete zip of the source files and a batch file to produce a  DLL and an EXE that uses the DLL. Open an IFort - 32 bit command window, and run the batch file.

s:\lang\sumdll\sum_cpp\tst>bld

s:\lang\sumdll\sum_cpp\tst>lib /def:sum_cpp.def /machine:i386
Microsoft (R) Library Manager Version 12.00.31101.0
Copyright (C) Microsoft Corporation.  All rights reserved.

   Creating library sum_cpp.lib and object sum_cpp.exp

s:\lang\sumdll\sum_cpp\tst>icl /LD sum_cpp.cpp sum_cpp.exp
Intel(R) C++ Compiler XE for applications running on IA-32, Version 15.0.4.221 Build 20150407
Copyright (C) 1985-2015 Intel Corporation.  All rights reserved.

sum_cpp.cpp
Microsoft (R) Incremental Linker Version 12.00.31101.0
Copyright (C) Microsoft Corporation.  All rights reserved.

-out:sum_cpp.dll
-dll
-implib:sum_cpp.lib
sum_cpp.obj
sum_cpp.exp

s:\lang\sumdll\sum_cpp\tst>ifort sum_test.f90 sum_cpp.lib
Intel(R) Visual Fortran Compiler XE for applications running on IA-32, Version 15.0.4.221 Build 20150407
Copyright (C) 1985-2015 Intel Corporation.  All rights reserved.

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

-out:sum_test.exe
-subsystem:console
-incremental:no
sum_test.obj
sum_cpp.lib

s:\lang\sumdll\sum_cpp\tst>sum_test
 add integers
         7 +         43 =         50

 

0 Kudos
PeterTheRascal
Beginner
3,994 Views

Many thanks mecej4, that is excellent.

I can see (from dumpbin) that you have managed the remove all  name-mangling from the dll and lib, so my Fortran happily links to it.

Your sum_cpp.def,  with "sum=_sum@8" is an easy and effective solution and I much recommend anyone interested in removing the C++ name-mangling to download your example in full!

Bravo

 

 

 

 

 

0 Kudos
Steven_L_Intel1
Employee
3,994 Views

I am not a fan of using .def files in this way. It will prevent you from building from x64. Better would be to remove STDCALL from the equation and use the Fortran C interoperability features, though if you need STDCALL we now allow you to use ATTRIBUTES STDCALL with BIND(C).

0 Kudos
mecej4
Honored Contributor III
3,994 Views

Steve, I agree with you in principle, but in this case the problem was with the C/C++ compiler. MS does not provide an "alias" pragma to control underscores and other decorators. GCC does, but then, ... So, with MS C, you have to pick from the attributes available, and adjust the names generated in the other OBJ files to suit. I suppose you could consider syscall, fastcall, etc.

0 Kudos
PeterTheRascal
Beginner
3,994 Views

Steve #11

I plan to eventually use Fortran C interoperability features, but for now DLLs are useful.

Steve>>   using .def files in this way .. will prevent you from building from x64

What is the issue with DEF in x64? Is it just that one needs a different DEF file  as it seems x64  un-mangles with just “sum” not “sum=_sum@8 ?

Steve>>  we now allow you to use ATTRIBUTES STDCALL with BIND(C).

Can you please  give me more details? Would this allow Fortran to link to an STDCALL DLL despite mangled-names?

0 Kudos
mecej4
Honored Contributor III
3,994 Views

Do you want to create a 64-bit version of your DLL to be callable from 64-bit Excel? Does 64-bit Excel use STDCALL? These may well be "I'll look at it later" types of questions.

0 Kudos
PeterTheRascal
Beginner
3,994 Views

Excel is not the reason I wish to support STDCALL for now.

0 Kudos
Reply