Sometimes you have an existing DLL and you need to call routines in it from R. Changing the contents of the DLL is not an option, but the DLL doesn't follow the R calling conventions. In this case, you probably need to write a wrapper DLL.
R is written using the MinGW port of gcc, and you'll get the best support from other R users if you write your wrapper in MinGW using C. The steps to follow are:
The easiest way to find the exports is using the MinGW utility function pexports. (This is not part of the R Windows toolset; you need to download it separately from the MinGW page, in the "MinGW Utilities" collection.) This will list the names of the functions, and from those one can often guess the calling convention. Exports that have a suffix @n, where n is a number, almost certainly use the stdcall convention. Exports with no suffix may use stdcall (e.g. Windows API functions), or cdecl, or another convention (e.g. if produced by Delphi). For example,
$ pexports teststdcall.dll LIBRARY teststdcall.dll EXPORTS dostdcall@8is an example where dostdcall is an exported function using the stdcallconvention. (I use the Cygwin bash shell, so the dollar sign "$" above is the command prompt. Doing this in the Windows CMD shell would be very similar.)
See Wu Yongwei's web page for more details about naming conventions.
$ pexports teststdcall.dll >teststdcall.defThen use dlltool -D <DLLname> -d <defs> -l <libname> to create the library, e.g.
$ dlltool -D teststdcall.dll -d teststdcall.def -l libteststdcall.aSee the Wiki for some other dlltool options.
__stdcall double dostdcall(double x);
void callit(double *x)
{
double y;
y = dostdcall(*x);
*x = y;
}
Put this in a file named e.g. callstdcall.c. You need to tell MinGW to include the import library
that you defined above. Do this using the "-L. -lteststdcall" option (NB: notice no "lib" in
the library name). You pass options to MinGW on its command line, or (better!) through the
PKG_LIBS environment variable when using Rcmd SHLIB. For example,
$ export PKG_LIBS="-L. -lteststdcall" $ Rcmd SHLIB callstdcall.c making callstdcall.d from callstdcall.c gcc -If:/R/svn/r-devel/R/include -Wall -O2 -c callstdcall.c -o callstdcall.o ar cr callstdcall.a callstdcall.o ranlib callstdcall.a gcc --shared -s -o callstdcall.dll callstdcall.def callstdcall.a -Lf:/R/svn/r-devel/R/src/gnuwin32 -L. -lteststdcall -lg2c -lR
> dyn.load('callstdcall.dll')
> .C('callit', x=as.double( ))
Last modified: $Date: 2006-07-06 15:47:05 -0400 (Thu, 06 Jul 2006) $, by Duncan Murdoch