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

Calling C++ MFC DLL (.net) from Intel Fortran DLL

westymanbc
Beginner
341 Views

Good Day,

We are a converting our Ocean Science suite of applications from Compaq Visual Fortran with
Visual C v6 to Intel Fortran with Visual Studio 2005 and are having some difficulty.

As a test I created a Fortran DLL project, and a C++ MFC DLL Project all in the same VS solution

TEST1 - works great
In the Fortran project I defined a Fortran function as available for export and this works fine
We have a separate C# solution that can call this just fine.

real function SquareRoot(myNumber)
!DEC$ ATTRIBUTES DLLEXPORT::SquareRoot
!DEC$ ATTRIBUTES ALIAS:'SquareRoot'::SquareRoot
!DEC$ ATTRIBUTES VALUE :: myNumber
REAL, INTENT(IN) :: myNumber
REAL mySquareRoot

mySquareRoot = SQRT(myNumber)
SquareRoot = mySquareRoot

end function SquareRoot

TEST2 - Linking Error
We have several Fortran programs that call C++ code so we tested this as follows
1.Create a simply c++ program
// Lets try and write a simple program now that fortran can call
// Firstly we must declare it to be an external C function
extern "C" __declspec(dllexport) int GetRandomInteger();

// Really simple - give us a number
int GetRandomInteger()
{
return 25;
}

2. I ran dumpbin to be sure the function was available for export

Dump of file testmfcdll.dll

File Type: DLL

Section contains the following exports for TestMFCDLL.dll

00000000 characteristics
4A424584 time date stamp Wed Jun 24 08:25:56 2009
0.00 version
1 ordinal base
1 number of functions
1 number of names

ordinal hint RVA name

1 0 00001050 GetRandomInteger = _GetRandomInteger

Summary

1000 .data
1000 .rdata
1000 .reloc
1000 .rsrc
2000 .text

3. I created a fortran function as follows in the fortran dll project
INTEGER FUNCTION GetNumberFromCPP()

INTERFACE TO FUNCTION GetRandomInteger()
!DEC$ ATTRIBUTES C, DLLIMPORT, DECORATE, ALIAS:'_GetRandomInteger'::GetRandomInteger
INTEGER GetRandomInteger
END

GetNumberFromCPP = GetRandomInteger()

END FUNCTION GetNumberFromCPP

When I compile the fortran dll project i get the dreaded LNK2019 error as follows:
error LNK2019: unresolved external symbol __imp___GetRandomInteger referenced
in function _GETNUMBERFROMCPP

NOTES:
I have tried the !DEC$ with and without "C","DECORATE","DLLIMPORT"
I have tried adding the lib file from the c++ dll to the fortran source directory
I have changed the name in the alias with/without "_"

I am a newby to fortran and c++ so I may have missed something very simple.

I appreciate any help ... Thanks Mike

0 Kudos
1 Solution
Lorri_M_Intel
Employee
341 Views
Quoting - westymanbc
Solved - changed the declaration to
!DEC$ ATTRIBUTES STDCALL, DLLIMPORT, ALIAS:'_GetRandomInteger'::GetRandomInteger

I know you said you did, but could you try this one again please?

!DEC$ ATTRIBUTES C, DLLIMPORT, ALIAS:'_GetRandomInteger'::GetRandomInteger

The aboveshould work too, and might be better. I worry what other side effects you might have by declaring the routine as STDCALL instead of C. There are calling-standard differences there that might bite you.

In your original version, the "DECORATE" put an extra underscore before the alias name, giving the three-underscores in the middle of the external name.

- Lorri


View solution in original post

11 Replies
westymanbc
Beginner
341 Views
Solved - changed the declaration to
!DEC$ ATTRIBUTES STDCALL, DLLIMPORT, ALIAS:'_GetRandomInteger'::GetRandomInteger
Lorri_M_Intel
Employee
342 Views
Quoting - westymanbc
Solved - changed the declaration to
!DEC$ ATTRIBUTES STDCALL, DLLIMPORT, ALIAS:'_GetRandomInteger'::GetRandomInteger

I know you said you did, but could you try this one again please?

!DEC$ ATTRIBUTES C, DLLIMPORT, ALIAS:'_GetRandomInteger'::GetRandomInteger

The aboveshould work too, and might be better. I worry what other side effects you might have by declaring the routine as STDCALL instead of C. There are calling-standard differences there that might bite you.

In your original version, the "DECORATE" put an extra underscore before the alias name, giving the three-underscores in the middle of the external name.

- Lorri


jayaraj_ind001yahoo_
341 Views

I know you said you did, but could you try this one again please?

!DEC$ ATTRIBUTES C, DLLIMPORT, ALIAS:'_GetRandomInteger'::GetRandomInteger

The aboveshould work too, and might be better. I worry what other side effects you might have by declaring the routine as STDCALL instead of C. There are calling-standard differences there that might bite you.

In your original version, the "DECORATE" put an extra underscore before the alias name, giving the three-underscores in the middle of the external name.

- Lorri


Hi,

I tried the same example, but getting some link errors.

C++ dll:

.cpp file

#include"attempt1.h"

// Really simple - give us a number
int __stdcall GetRandomInteger()
{
return 25;
}

.h file


extern "C" int __stdcall GetRandomInteger();

.def file

LIBRARY "Attempt"
;CODE PRELOAD MOVEABLE DISCARDABLE
;DATA PRELOAD MOVEABLE SINGLE
;HEAPSIZE 1024
EXPORTS
GetRandomInteger


Fortran dll: .lib file of above C++ was added as resource file in this project

.f file

FUNCTION GetNumberFromCPP()


INTERFACE to FUNCTION GetRandomInteger()
!DEC$ ATTRIBUTES C, DLLIMPORT, ALIAS:'_GetRandomInteger'::GetRandomInteger

Integer GetRandomInteger
END

Integer GetNumberFromCPP

GetNumberFromCPP = GetRandomInteger()

END FUNCTION GetNumberFromCPP


Error:

error LNK2019: unresolved external symbol _getrandominteger@0 referenced in function _getnumberfromcpp

1>DebugConnect.dll : fatal error LNK1120: 1 unresolved externals

Please help me as i am new to this interface.

Regards,
Jayaraj

jirina
New Contributor I
341 Views
Recently, I have been dealing with this too. I did following to make things work:

1. In C++ (I am using Microsoft VS 2008), I have
[cpp]extern "C" {
__declspec(dllexport) int __stdcall InitSignalProcessing( void );
}
__declspec(dllexport) int __stdcall InitSignalProcessing( void )
{
return (int) SetConsoleCtrlHandler( (PHANDLER_ROUTINE) CtrlHandler, TRUE );
}[/cpp]
Please note that you are probably missing __declspec(dllexport) in your code. The .def file seems OK.

2. In Fortran, I have
[cpp]interface
integer*4 function InitSignalProcessing ( ) !dec$ attributes stdcall, dllimport, decorate, alias: "InitSignalProcessing" :: InitSignalProcessing end function
end interface[/cpp]
Note that there is no leading underscore in alias:"InitSignalProcessing" :: InitSignalProcessing.

I have a console application in Fortran, not a dll, so I am adding the .lib file into the additional dependencies of the linker (/IMPLIB: myDll.lib). It might be interesting for you that I am using the C++ dll as delay-loaded (/DELAYLOAD: "myDll.dll").
genaganna
Beginner
341 Views
Quoting - jirina
Recently, I have been dealing with this too. I did following to make things work:

1. In C++ (I am using Microsoft VS 2008), I have
[cpp]extern "C" {
__declspec(dllexport) int __stdcall InitSignalProcessing( void );
}
__declspec(dllexport) int __stdcall InitSignalProcessing( void )
{
return (int) SetConsoleCtrlHandler( (PHANDLER_ROUTINE) CtrlHandler, TRUE );
}[/cpp]
Please note that you are probably missing __declspec(dllexport) in your code. The .def file seems OK.

2. In Fortran, I have
[cpp]interface
integer*4 function InitSignalProcessing ( )
!dec$ attributes stdcall, dllimport, decorate, alias: "InitSignalProcessing" :: InitSignalProcessing
end function
end interface[/cpp]
Note that there is no leading underscore in alias:"InitSignalProcessing" :: InitSignalProcessing.

I have a console application in Fortran, not a dll, so I am adding the .lib file into the additional dependencies of the linker (/IMPLIB: myDll.lib). It might be interesting for you that I am using the C++ dll as delay-loaded (/DELAYLOAD: "myDll.dll").

Hi Jirina,

could you please explain how to do same thing with ISO_C_BINDING module?

I tried i am getting linker error saying that function is undefined.


jirina
New Contributor I
341 Views
I am sorry, I have never used ISO_C_BINDING, so I don't know how to use it. I myself would appreciate a small example how to call a method from a C++ DLL from Fortran using ISO_C_BINDING; I was not able to find any. :-[
Steven_L_Intel1
Employee
341 Views
ISO_C_BINDING is not relevant here. There is the BIND(C) clause, but you can't use that with STDCALL.
IanH
Black Belt
341 Views
Minimal example that uses C interoperability (BIND(C) etc - so the calling convention is not stdcall): FortranToCppDLL.zip.

Non-defaultish things:
  • The C++ program was a C++ empty project that had its General > Configuration type changed to be a DLL.
  • The fortran program's General > Output directory is set to be the solution's output directory (so the DLL and exe end up in the same place).
  • The fortran program's Libraries > Runtime library is set to be the DLL flavour (so we don't end up with multiple runtimes).
  • The Fortran project's "Project Dependencies" include the C++ project.
genaganna
Beginner
341 Views
Quoting - IanH
Minimal example that uses C interoperability (BIND(C) etc - so the calling convention is not stdcall): FortranToCppDLL.zip.

Non-defaultish things:
  • The C++ program was a C++ empty project that had its General > Configuration type changed to be a DLL.
  • The fortran program's General > Output directory is set to be the solution's output directory (so the DLL and exe end up in the same place).
  • The fortran program's Libraries > Runtime library is set to be the DLL flavour (so we don't end up with multiple runtimes).
  • The Fortran project's "Project Dependencies" include the C++ project.


How to do if c function defined with STDCALL. as we know most of the c libraries shipped with STDCALL


if i added __stdcal to C function in your samples

extern "C" int __declspec(dllexport) __stdcall a_function(double arg)

I am getting following error

2>Compiling with Intel Visual Fortran 11.1.038 [IA-32]...
2>FortranToCppDLL.f90
2>Linking...
2>FortranToCppDLL.obj : error LNK2019: unresolved external symbol _a_function referenced in function _MAIN__
2>C:Documents and SettingsAdministratorDesktopFortranToCppDLLDebugFortranProgram.exe : fatal error LNK1120: 1 unresolved externals


could anybody please explain how to do this with BIND(C)?

I am using Visual fortran 11.1

Steven_L_Intel1
Employee
341 Views
BIND(C) cannot be used with STDCALL. If you are calling a STDCALL routine, you'll have to do it with !DEC$ ATTRIBUTES.
genaganna
Beginner
341 Views
BIND(C) cannot be used with STDCALL. If you are calling a STDCALL routine, you'll have to do it with !DEC$ ATTRIBUTES.


I have to use preprocessor flags inoder to work with both intel and gfortran compilers.


Thank you for all
Reply