dyncall(3)
NAME
dyncall – encapsulation of architecture-, OS- and compiler-specific
function call semantics
SYNOPSIS
#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);
DESCRIPTION
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.
EXAMPLE
Let's say, we want to make a call to the function:
double sqrt(double x);
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);
CONFORMING TO
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.
SEE ALSO
dyncallback(3), dynload(3) and the dyncall manual (available in HTML and
PDF format) for more information.
AUTHORS
Daniel Adler ⟨dadler@uni-goettingen.de⟩
Tassilo Philipp ⟨tphilipp@potion-studios.com⟩
December 17, 2021