calling C for Dummies

calling C for Dummies

Hi,
I have these C & C++ routines that I want to compile into my dll. I have no clue about C and all the examples I have in the literature show how to call Fortran from C and not the other way around. Help!
I intend on compiling these routines into my dll - they are from the generic.xll example for making native Excel addins. Any hints?

4 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

There are many ways -- I'll explain the one I typically use. I'll assume Visual C++ on the C side; with other compilers dllexport directives are different.
All C functions should have the following prototype (stated in both .h and .cpp) file. Typically, this is done using a #define:

 
#define MYAPI extern "C" __declspec(dllexport) // Only in .h file 
 
MYAPI int/void/whatever __stdcall CFunc()   //In both .h and .cpp file 

Next, on the Fortran side, create interface blocks (in include file or, better, in a module) using the following rules:

- Void->SUBROUTINE, other->FUNCTION

- All routines should have !DEC$ATTRIBUTES STDCALL, DLLIMPORT

- All routines should have ALIAS. Mangled name begins with underscore,
it's case-sensitive and ends with @ plus no. of arguments x 4. You can use command-line tool dumpbin /exports mydll.dll to see exact mangled name.
- Pointer (*) or reference (&) arguments should have !DEC$ATTRIBUTES REFERENCE. Frequently, in apis there's a #define somewhere for pointers-to-something starting with LP (e.g. LPCTSTR is pointer-to-string)

Here's a small example:

 
MyDll.h==8<=============== 
#define MYAPI extern "C" __declspec(dllexport) 
 
MYAPI int GetAString(int i, char* szString) 
MyDll.cpp==8<=============== 
#include MyDll.h 
MYAPI int GetAString(int i, char* pszString) 
{ 
    sprintf(pszString. "%5d", i);  //Equal to Fortran internal WRITE 
    return 10; 
} 
Interfaces.f90==8<=============== 
MODULE INTERFACES 
 
INTERFACE 
    INTEGER FUNCTION GetAString(i, s) 
    !DEC$ATTRIBUTES STDCALL, DLLIMPORT, ALIAS: "_GetAString@8":: GetAString 
    INTEGER:: i 
    !DEC$ATTRIBUTES REFERENCE:: s 
    CHARACTER(*):: s 
    END FUNCTION 
END INTERFACE 
 
END MODULE INTERFACES 
Code.f90==8<=============== 
USE INTERFACES 
 
CHARACTER(20):: sTemp 
 
j = GetAString(15, sTemp) 
WRITE(*,*) sTemp 

Don't forget to add MyDll.lib to your Fortran project (just as any source file).

HTH
Jugoslav

I have a follow-up question:

What if the c code is in a DLL developed by a third party and the location of that DLL will only be known when my CVF executable is installed in the user's computer? In other words, how to specify the location of that DLL at runtime?

Is it sufficient to have the DLL somewhere in the command path? Are there any (more elegant and robust) alternatives to the command path?

Thanks,

Gabriel

See for example LoadLibrary entry in platform SDK help for description on order of how Windows determines which library to load. Actually, it would be a good idea to read entire Windows Base Services/Executables/Dynamic-link libraries chapter. In short, when using "Load-time dynamic linking" method (i.e. including .lib into your project), you can't determine the path from which the dll will be loaded -- it's determined by Windows as described in LoadLibrary. If that's not OK for you,
you might resort to "Run-time binding", i.e. using LoadLibrary instead of .lib file.
Then, the changes in my sample would be:

- omit ALIAS and DLLIMPORT directives in INTERFACE;

- add POINTER(pGetAString, GetAString) statement immediately after INTERFACE block;

- use the following piece of code to call:

 
hLibrary = LoadLibrary("C:SomewhereSome.dll"//CHAR(0)) 
IF (hLibrary .NE. 0) THEN !DLL exists 
   pGetAString = GetProcAddress(hLibrary, "_GetAString@8"C) 
   IF (pGetAString .NE. 0) THEN !It does export GetAString function 
      j = GetAString(15, sTemp) 
   END IF 
END IF 

Call FreeLibrary(hLibrary) when you don't need the dll anymore. Also, you can call GetProcAddress only once (it determines function's address) and call GetAString as many times as you want afterwards.

Jugoslav

Leave a Comment

Please sign in to add a comment. Not a member? Join today