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

Calling Fortran DLL from C++ DLL using Visual Studio 2015

Matteo_S_
Beginner
3,158 Views

Dear All,

I have a DLL written in C++ and a program written in Fortran. What I need to do is to transform the Fortran program into a DLL and make the C++ DLL able to call it.

I read several topics on this forum but I am still having trouble: LoadLibrary fails. I don't know if this is a problem due to errors in compiling the Fortran DLL or due to errors in the C++ side.

So far I have:

- Fortran side:

!!!!!PROGRAM MAIN
MODULE MAIN

USE, INTRINSIC :: ISO_C_Binding

USE MODULE_Subs  ! This has all the subroutines needed in the program

IMPLICIT  NONE

CONTAINS

SUBROUTINE FORTRAN_DLL ( ind_TimeStep, avrSWAP ) BIND (C, NAME='FORTRAN_DLL')
!DEC$ ATTRIBUTES DLLEXPORT :: FORTRAN_DLL

IMPLICIT  NONE

INTEGER(C_INT),         INTENT(IN)    :: ind_TimeStep
REAL(C_FLOAT),          INTENT(INOUT) :: avrSWAP   (*)


!!!!! Instructions


RETURN

CONTAINS

!!!!! Some other subroutines used only here

!!!!!END PROGRAM MAIN
END SUBROUTINE FORTRAN_DLL

END MODULE MAIN

 

- C++ side:

#define _CRT_SECURE_NO_DEPRECATE 1
#define _CRT_SECURE_NO_WARNINGS  1

#include <windows.h> //CED - for external DLL management
#include <fstream>

HINSTANCE h_FORTRAN_dll;

typedef void (*__FORTRAN_DLL)(int, float *);

__FORTRAN_DLL  FORTRAN_DLL;

// Variables for FORTRAN DLL
int ind_TimeStep = 1;

//avoid mangled names
extern "C"
{
void __declspec(dllexport) __cdecl C_DLL(float *avrSwap,
                             int *aviFail,
                             char *accInfile,
                             char *avcOutname,
                             char *avcMsg);
}

//Main DLL routine
void __declspec(dllexport) __cdecl C_DLL (float *avrSwap,
                             int *aviFail,
                             char *accInfile,
                             char *avcOutname,
                             char *avcMsg)
{

			if (!(h_FORTRAN_dll = LoadLibrary(".\..\Folder\FORTRAN_DLL.dll")))
			{
				printf("\n*** FORTRAN_DLL.dll not found. Aborting.\n"); exit(-1); return;
			}

			FORTRAN_DLL = (__FORTRAN_DLL)GetProcAddress(h_FORTRAN_dll, "FORTRAN_DLL");


			FORTRAN_DLL(ind_TimeStep, avrSwap );

			ind_TimeStep = ind_TimeStep + 1;


}

This C++ DLL does not have to do anything but pass avrSWAP(coming from the main program) to the Fortran DLL.

C++ DLL is compiled in release version in Win32 Configuration.

Fortran DLL is compiled in release versione in x86 Configuration.

 

Any help would be appreciated.

Thank you in advance

 

Best regards,

Matteo Strada

0 Kudos
22 Replies
Matteo_S_
Beginner
576 Views

Thank you Jim, I'll have a look.

0 Kudos
Matteo_S_
Beginner
576 Views

Dear All,

I need your help again.

Now I can successfully load and call the Fortran_DLL.dll whenever the main C++ program needs it.

Now I need to control it better. The original Fortran program is divided in 3 sections:

- Initialization

- First Solution (Solution_0)

- Solution Loop for every time step

What I am trying to do is the following. 

Differently from the orginal post, I made some changes. The DLL is no more a MODULE and so the "MainFile.F90" has only the FORTRAN_DLL subroutine:

SUBROUTINE FORTRAN_DLL
IF FirstCall THEN
   Initialization
   Solution0(Time0)
ELSE
   Solution(CurrentTime)
END
END SUBROUTINE FORTRAN_DLL

I am able to make DLL aware if it is the first time it is being called or not.

While at the FirstCall the DLL works since it passes from the Initialization subroutine, at the very next call it doesn't work since it has no memory of what has been initializated(i.e. all the parameters read from the input files are no more available). The Initialization subroutine stores all the parameters in a giant TYPE.

So, how can I save in memory this TYPE from the first call? Furthermore I have the constraint that the Initialization subroutine has to be called only once, so I definitely need to save that TYPE. This is because the Initialization subroutine has also the task of opening the output files in order to be written in the 2 Solution subroutines. If I call the Initialization on every call for the FORTRAN_DLL it gives me error.

I am thinking of splitting the FORTRAN_DLL into 2 different subroutines: FORTRAN_DLL_INIT(with Initialization and Solution0) and FORTRAN_DLL (with Solution) but again I need the Initialization TYPE to be stored somewhere.

Any help would be appreciated.

Thank you in advance.

Best Regards,

Matteo Strada

0 Kudos
Reply