dyncall {rdyncall}R Documentation

Foreign Function Interface to compiled code with support for multiple calling conventions.

Description

Functions to make calls to compiled code with support for multiple calling conventions.

Usage

.dyncall( address, signature, ... , callmode = c("cdecl","stdcall") )

.dyncall.cdecl        ( address, signature, ... )
.dyncall.stdcall      ( address, signature, ... )

Arguments

address An external pointer to a foreign function.
signature A character string specifying the argument and return type of a function call.
callmode A character string specifying the calling convention.
... Any arguments to be passed via dyncall according to the argument types specified in signature.

Details

A valid address to a foreign function can be obtained from functions such as .dynfind and getNativeSymbolInfo.

Value

The return value of the foreign function call converted to an R type according to the return type character given by signature.

test

The signature is a character string that encodes the arity (number of arguments) and formal argument- and return-types using a character-based type code.

The calling convention is specified explicitly by the callmode argument using .dyncall or implicitly by using .dyncall.* functions.

The arguments given with ... are passed and possibly converted according to the given signature.

Signature

The general form of a dyncall signature string is

Argument types ) Return type

A type is specified using a one-character type code. The argument type characters are specified in left-to-right order of the corresponding C function prototype. A closing bracket character ')' marks the end of input argument types. Finally, a return type character is given to specify the return value. The following table lists valid type character codes, corresponding C types, acceptable R argument types and returned R types.

Type code C type R argument type R return type
B bool raw,logical,integer,double logical
c char raw,logical,integer,double integer
C unsigned char raw,logical,integer,double integer
s short raw,logical,integer,double integer
S unsigned short raw,logical,integer,double integer
i int raw,logical,integer,double integer
I unsigned int raw,logical,integer,double double
j long raw,logical,integer,double double
J unsigned long raw,logical,integer,double double
l long long raw,logical,integer,double double
L unsigned long long raw,logical,integer,double double
f float raw,logical,integer,double double
d double raw,logical,integer,double double
p type* (pointer) any vector,externalptr,NULL externalptr,NULL
S char* character,NULL character,NULL
x SEXP any any
v void invalid NULL

Some examples of C function prototypes and corresponding function type signatures:

double sqrt(double); "d)d"
double dnorm(double,double,double,int); "dddi)d"
void R_isort(int*,int); "pi)v"
char foo(int,double,float,bool); "idfB)c"
void revsort(double*,int*,int); "ppi)v"

How-to connect to a library

Calling conventions

Calling conventions specify exact low-level information how a function call is invoked. The conventions differ heavily from CPU type to CPU type. Some conventions are related to OS and Compiler issues. While on many processor architectures, there is only one general calling convention - there is choice on x86 processor architectures and in particular when working with Microsoft Windows system libraries.

In general, many prebuilt binaries available online will work fine with "cdecl".

"cdecl"
Default C calling convention.
"stdcall"
Available on the X86 architecture, otherwise falls back to "cdecl". Use when linking Microsoft Windows System Libraries (e.g. KERNEL32.DLL, USER32.DLL, OPENGL32.DLL ...).
"thiscall.gcc"
Available on the X86 architecture, otherwise falls back to "cdecl". Use when calling C++ member functions that are linking x86 C++ shared libraries compiled with GCC using __thiscall.
"thiscall.msvc"
Available on the X86 architecture, otherwise falls back to "cdecl". Use when linking x86 shared libraries compiled with Visual C++ using __thiscall.
"fastcall.msvc"
Available on the X86 architecture, otherwise falls back to "cdecl".
"fastcall.gcc"
Available on the X86 architecture, otherwise falls back to "cdecl".

In many cases, "cdecl" is the best choice. Exceptions to this include, X86 architectures and in particular Microsoft Windows platforms.

WARNING: non-X86 platforms are immune against wrong calling conventions, as there is only one.

The calling convention is defined during compilation of shared libraries. One specifies the calling convention using function prototype attributes such as __attribute__((stdcall)) or __stdcall for short.

On X86 Architectures, the fastcall and thiscall (C++) calling convention differ regarding Microsoft Visual C++ and the GCC compilers. "fastcall.msvc" and "thiscall.msvc" are used for the Microsoft Visual C++ compiled code, while "fastcall.gcc" and "fastcall.gcc" use GCC compiled code.

Note

When invoking a foreign function calls, the address, calling convention and type information for arguments and return values MUST match with the compiled function. Otherwise the invocation can lead to a fatal system crash.

Calling functions via dyncall is very TYPE UNSAFE. Some safety is achieved. Dyncall does not perform any call, if you missed the arity of the function given with the signature and probably fails on several type-incompatibilities. But in general, there is no safe way to test if the pointer given, is a valid function pointer. Thus, this package can cause unexpected behaviour if the user is not aware of what she is doing. USE ON YOUR OWN RISK.

References

Adler, D., Philipp, T. (2008) DynCall Library. http://dyncall.org

See Also

getNativeSymbolInfo and .dynfind. .C,.Call,,.External

Examples

# load 'R' dynport
libR <- .dynload("R")
reg.finalizer(libR, .dynunload)
.dynfind(.libR, "") 
# load platform-specific standard C DLL
 
clibname <- "libc"
if (.Platform$OS.type == "windows") clibname <- "msvcrt"
if (.Platform$OS.type == "darwin") clibname <- "libc.dylib"
if (.Platform$OS.type == "linux") clibname <- "libc.so.6"

dyn.load(clibname)
sqrt.ptr <- getNativeSymbolInfo("sqrt")
mysqrt <- function(x) .dyncall.cdecl(sqrt.ptr, "d)d", x)

aDouble <- 144
anInteger <- 144L

mysqrt(aDouble)
mysqrt(anInteger)

clib <- rdcLoad(clibname)

# call sqrt function

sqrt.fp <- rdcFind(clib,"sqrt")
print( rdcCall(sqrt.fp, "d)d", 144) )


[Package rdyncall version 0.1 Index]