| dyncall {rdyncall} | R Documentation |
Functions to make calls to compiled code with support for multiple calling conventions.
.dyncall( address, signature, ... , callmode = c("cdecl","stdcall") )
.dyncall.cdecl ( address, signature, ... )
.dyncall.stdcall ( address, signature, ... )
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. |
A valid address to a foreign function can be obtained from functions such as .dynfind and getNativeSymbolInfo.
The return value of the foreign function call converted to an R type according to the return type character
given by signature.
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.
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" |
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""stdcall""thiscall.gcc"__thiscall."thiscall.msvc"__thiscall. "fastcall.msvc""fastcall.gcc"
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.
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.
Adler, D., Philipp, T. (2008) DynCall Library. http://dyncall.org
getNativeSymbolInfo and .dynfind.
.C,.Call,,.External
# 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) )