FAQ: Using DLLS with G95

Q: Where can I find information about making and using dlls with g95?

A: Search for previous postings in the archive of the g95 newsgroup on how to make a dll.

Stdcall and DLL tools of MSVC and MinGW: http://www.geocities.com/yongweiwu/stdcall.htm


Q: What is a dll? A: DLL is an acronym for "Dynamic Link Library." Dlls are commonly used on MS Windows. A dll typically consists of one or more subroutines that are compiled into a library to be called by other programs. Programs compiled with g95 can statically link to subroutines in dlls. G95 compiled dlls can be used by other programs. Dynamic linking is not currently supported by g95, but can be implemented as explained here.

Q: Is there an advantage to using a dll?

A: Dlls can be called by programs such as Visual Basic, Word, or Excel.

Q: What command line should I use with g95?

A: This example produces a dll called ex.dll. Save the code below in file ex.f90.

subroutine ex(i)
integer i
i=i+1
return
end
 
Compile and generate the dll with the following commands:

g95 -c ex.f90
g95 -shared -mrtd -o ex.dll ex.o
 
-c Compile only, producing the object file ex.o
-o Names the output file ex.dll
-shared Creates the dll
-mrtd Sets the calling convention to stdcall

By default g95 internal functions are included in the dll.

Here is a test program that calls the dll.

$ cat > mytest.f90

! A test program to call ex.dll

integer :: i
i = 6
call ex(i)
print *, i
end

$ g95 -o mytest mytest.f90 -L. ex.dll


$ mytest
 7

$

Q. What is the stdcall calling convention?

A: Explanations are provided at the following links:

http://www.programmersheaven.com/2/Calling-conventions#stdcall
http://www.cs.cornell.edu/courses/cs412/2001sp/resources/microsoft-calling-conventions.html

Q. Can I compile the g95 library to work with dlls?

A. Yes, instructions for the build are in the Compilation Notes page, at http://www.g95.org/src.shtml#Build.

Q. Can a dll compiled with g95 be loaded dynamically?

A. The example below, adapted from code provided by David Miles, shows how to include a small C program with dlls compiled with g95 to load a dll dynamically. This requires that the g95 library is compiled as explained on the Compilation Notes page. The object file g95main.o must be present in the /lib directory. The files are included in the g95 Cygwin binary distribution. The idea behind this approach is to link in g95 as a library, which causes the GNU build system to ignore a second "main" function. When executing the program, the files main.exe, dll1.dll and dll2.dll should all be present in the current working directory.

Save the code below as dll1.f90

subroutine dll1
  real :: arr(2,2)
  call random_number(arr)
  print*,arr
! call dll2
  call dynload
end subroutine dll1

Save the code below as dll2.f90

subroutine dll2
  integer :: n=10
  call sub1(n)
contains
  subroutine sub1(n)
    real :: arr(n,n)
print*,'here'
    call random_number(arr)
print*,'done'
  end subroutine sub1
end subroutine dll2

Save the code below as main.f90

program m
  call dll1
end program m

Save the following code as load.c. This code is compiled and the object code linked into dll1, to load dll2 dynamically at runtime. 

// load.c - Cygwin version

#include <dlfcn.h>
#include <stdio.h>
#include <errno.h>

void dynload_() {
   void (*Function)(),*Handle;
   Handle = dlopen( "dll2.dll", RTLD_NOW );
   if ( Handle == NULL ) {
     fprintf( stderr, "can't load: %s\n", dlerror() );
     exit(0);
   }
   Function = (void(*)())dlsym( Handle,"dll2_" );
   if ( Function == NULL ) {
     fprintf( stderr, "can't find function dll2_: %s\n", dlerror() );
     exit(0);
   }
   (*Function)();
}

In MinG use this version:

// load.c - MinGW version

#include <windows.h>

void dynload_() {
  typedef void (*pfunc)();
  HANDLE hdll;
  pfunc sub1;
  hdll = LoadLibrary("dll2.dll");
  sub1 = (pfunc)GetProcAddress(hdll, "dll2_");
  sub1();
  return;
}

Compiling:

gcc -c load.c
g95 -shared -Wl,--enable-auto-import -o dll1.dll dll1.f90 load.o
g95 -shared -Wl,--enable-auto-import -o dll2.dll dll2.f90 dll1.dll
g95 -o main main.f90 /lib/g95main.o -L. dll1.dll

Output:

$ main.exe
 0.8784881 0.18738759 0.47982866 0.24209005
 here
 done
$

Q. What tools are available for working with dlls?

A. The binutils package includes the following tools:

objdump: Display information from object files
objcopy
Copy and translate object files
nm:
List symbols from object files
dlltool:
Create files needed to build and use dlls
strip: Discard debug symbols
ar
Create, modify, and extract from archives
ranlib
Generate index to archive contents

Microsoft provides PEDUMP.  There is information about using the pedump utility in this series of articles (1), (2). 

SmidgeonSoft offers a free Windows Debugger, Disassembler, and Code Analyzers

More info: DLL Creation in MingW.