Home > other >  Call Fortran DLL from a C DLL without using LoadLibrary (Visual Studio)
Call Fortran DLL from a C DLL without using LoadLibrary (Visual Studio)

Time:03-16

I have some C code that I compile to a dll object.

I have a separate project, written in Fortran, which I too compile to a single dll object.

I need to call a function inside the Fortran dll from the C dll, without using LoadLibrary. I also need the 2 dll to remain separate, so I can replace one or the other without re-compiling them together.

I have read some information on the topic, but I can't get it to work. The compiler does not throw errors or warnings, but when I start my main program it fails. Here's what I tried:

  • I have declared all functions I wish to call from the C code with BIND ("C", NAME="FUNCNAME")

  • I have declared the USE, INTRINSIC :: ISO_C_Binding inside the functions and subroutines I intend to call from the C code

  • I included !DEC$ ATTRIBUTES DLLEXPORT :: NAME inside the Fortran code (I am using ifort)

  • I use c type variables in my Fortran code

  • I pass variables by reference in the C code

  • I included the Fortran dll .lib file as a source file to the C project

According to most sources and docs I consulted, I should be able to simply do the following:

In Fortran:

SUBROUTINE FORTRANDLLFUNCTION(arg1, arg2, arg3, char1) BIND (C, NAME='FORTRANDLLFUNCTION')
USE, INTRINSIC  :: ISO_C_Binding

IMPLICIT NONE

!DEC$ ATTRIBUTES DLLEXPORT :: FORTRANDLLFUNCTION

REAL(C_FLOAT),                  INTENT(INOUT)   :: arg1
REAL(C_FLOAT),                  INTENT(INOUT)   :: arg2
REAL(C_FLOAT),                  INTENT(INOUT)   :: arg3
CHARACTER(KIND=C_CHAR),         INTENT(IN   )   :: char1

<do stuff>
END SUBROUTINE FORTRANDLLFUNCTION

In C:

extern void FORTRANDLLFUNCTION(float**, float**, float**, char*, int);

float a, b, c;
char abc;

FORTRANDLLFUNCTION(&a, &b, &c, abc, sizeof(abc));

However, I get an error when running the main program. If I remove the call to the Fortran function and run the main program with the compiled C dll, it works. What could be the source of my problem?

This is the output of dumpbin /exports on the compiled Fortran dll: enter image description here

And this is the result of dumpbin /imports on the compiled C dll: enter image description here

CodePudding user response:

So I finally found the cause of my problems...

I abandoned this and focused on a different part of the project, which led me to finding out that the reason why I was getting this error is that the Fortran dll didn't have to be in the same dir as the C dll, but the same dir as the exe calling the C dll (the C dll being in a different location).

It really surprises me as the error I was getting was "Can't load C.dll", instead of "Could not find/load fortran.dll", the correct traceback or message could have saved me hours...

Either ways, I believe it wouldn't have worked anyways had it not been for the comments made by @Mgetz, so thanks for that, really!

Some more clarifications to some of the comments on the question:

Before I finally realized what the solution was, and on top of creating my VS projects using cmake .. -G "Visual Studio 17 2022" -A x64, I also performed a dumpbin /headers on both the Fortran dll and the C dll, which both revealed that the machine was 8664 (64 bits architecture).

I use float** and int** in the Fortran dll function prototype in the C code because I call the Fortran function from within a C function which already takes pointers as arguments, so if I don't use "double pointers" when calling the Fortran function I get warnings from the compiler.

And yes, the Fortran runtime libraries were in the environment, I regularly work with Fortran, I knew that was not an issue.

  • Related