dyncall
—
encapsulation of architecture-, OS- and compiler-specific
function call semantics
#include <dyncall.h>
DCCallVM *
dcNewCallVM
(DCsize
size);
void
dcFree
(DCCallVM
* vm);
void
dcMode
(DCCallVM
* vm, DCint
mode);
void
dcReset
(DCCallVM
* vm);
void
dcArgBool
(DCCallVM
* vm, DCbool
arg);
void
dcArgChar
(DCCallVM
* vm, DCchar
arg);
void
dcArgShort
(DCCallVM
* vm, DCshort
arg);
void
dcArgInt
(DCCallVM
* vm, DCint
arg);
void
dcArgLong
(DCCallVM
* vm, DClong
arg);
void
dcArgLongLong
(DCCallVM
* vm, DClonglong
arg);
void
dcArgFloat
(DCCallVM
* vm, DCfloat
arg);
void
dcArgDouble
(DCCallVM
* vm, DCdouble
arg);
void
dcArgPointer
(DCCallVM
* vm, DCpointer
arg);
DCvoid
dcCallVoid
(DCCallVM
* vm, DCpointer
funcptr);
DCbool
dcCallBool
(DCCallVM
* vm, DCpointer
funcptr);
DCchar
dcCallChar
(DCCallVM
* vm, DCpointer
funcptr);
DCshort
dcCallShort
(DCCallVM
* vm, DCpointer
funcptr);
DCint
dcCallInt
(DCCallVM
* vm, DCpointer
funcptr);
DClong
dcCallLong
(DCCallVM
* vm, DCpointer
funcptr);
DClonglong
dcCallLongLong
(DCCallVM
* vm, DCpointer
funcptr);
DCfloat
dcCallFloat
(DCCallVM
* vm, DCpointer
funcptr);
DCdouble
dcCallDouble
(DCCallVM
* vm, DCpointer
funcptr);
DCpointer
dcCallPointer
(DCCallVM
* vm, DCpointer
funcptr);
void
dcArgF
(DCCallVM
* vm, const DCsigchar *
signature,
...);
void
dcVArgF
(DCCallVM
* vm, const DCsigchar *
signature, va_list
args);
void
dcCallF
(DCCallVM
* vm, DCValue *
result, DCpointer
funcptr, const DCsigchar
* signature,
...);
void
dcVCallF
(DCCallVM
* vm, DCValue *
result, DCpointer
funcptr, const DCsigchar
* signature, va_list
args);
The dyncall
library encapsulates architecture-, OS- and
compiler-specific function call semantics in a virtual "bind argument
parameters from left to right and then call" interface allowing
programmers to call C functions in a completely dynamic manner.
In other words, instead of calling a function directly, the
dyncall
library provides a mechanism to push the
function parameters manually and to issue the call afterwards.
Since the idea behind this concept is similar to call dispatching
mechanisms of virtual machines, the object that can be dynamically loaded
with arguments, and then used to actually invoke the call, is called CallVM.
It is possible to change the calling convention used by the CallVM at
run-time. Due to the fact that nearly every platform comes with one or more
distinct calling conventions, the dyncall
library
project intends to be a portable and open-source approach to the variety of
compiler-specific binary interfaces, platform specific subtleties, and so
on...
dcNewCallVM
() creates a new CallVM object,
where size specifies the max size of the internal
stack that will be allocated and used to bind the arguments to. Use
dcFree
() to destroy the CallVM object.
dcMode
() sets the calling convention to
use. See dyncall.h for a list of available modes. Note that some
mode/platform combinations don't make any sense (e.g. using a PowerPC
calling convention on a MIPS platform) and are silently ignored.
dcReset
() resets the internal stack of
arguments and prepares it for a new call. This function should be called
after setting the call mode (using dcMode), but prior to binding arguments
to the CallVM (except for when setting mode DC_SIGCHAR_CC_ELLIPSIS_VARARGS,
which is used prior to binding varargs of variadic functions). Use it also
when reusing a CallVM, as arguments don't get flushed automatically after a
function call invocation. Note: you should also call this function after
initial creation of the a CallVM object, as dcNewCallVM doesn't do this,
implicitly.
dcArgBool
(),
dcArgChar
(), dcArgShort
(),
dcArgInt
(), dcArgLong
(),
dcArgLongLong
(),
dcArgFloat
(), dcArgDouble
()
and dcArgPointer
() are used to bind arguments of the
named types to the CallVM object. Arguments should be bound in
left to right order regarding the C function
prototype.
dcCallVoid
(),
dcCallBool
(), dcCallChar
(),
dcCallShort
(), dcCallInt
(),
dcCallLong
(),
dcCallLongLong
(),
dcCallFloat
(),
dcCallDouble
() and
dcCallPointer
() call the function with the bound
arguments and returning the named type, where funcptr
is a pointer to the function to call. After the invocation of the function
call, the argument values are still bound to the CallVM and a second call
using the same arguments can be issued. Call reset
()
to clear the internal argument stack.
dcArgF
(),
dcVArgF
(), dcCallF
() and
dcVCallF
() can be used to bind arguments in a
printf-style call, using a signature string encoding the argument types and
return type. The former 2 only bind the arguments to the
vm object (and ignore return types specified in the
signature), whereas the latter two issue a call to the given function
pointer, afterwards. The return value will be stored in
result. The signature string also features calling
convention mode selection. For information about the signature format, refer
to the dyncall
manual in PDF format.
Let's say, we want to make a call to the function:
Using the dyncall
library, this function
would be called as follows:
double r;
DCCallVM* vm = dcNewCallVM(4096);
dcMode(vm, DC_CALL_C_DEFAULT);
dcReset(vm);
dcArgDouble(vm, 4.2373);
r = dcCallDouble(vm, (DCpointer)&sqrt);
dcFree(vm);
The dyncall library needs at least a c99 compiler with additional support for
anonymous structs/unions (which were introduced officially in c11). Given that
those are generally supported by pretty much all major c99 conforming
compilers (as default extension), it should build fine with a c99 toolchain.
Strictly speaking, dyncall conforms to c11, though.
Daniel Adler ⟨dadler@uni-goettingen.de⟩
Tassilo Philipp
⟨tphilipp@potion-studios.com⟩