Mercurial > pub > dyncall > dyncall
view dyncallback/dyncallback.3 @ 544:111236b31c75
- C++ non-trivial aggregate-by-value handling:
* dyncallback support for dcbArgAggr()
* better doc
author | Tassilo Philipp |
---|---|
date | Tue, 31 May 2022 18:25:13 +0200 |
parents | 71c884e610f0 |
children | fd7426080105 |
line wrap: on
line source
.\" Copyright (c) 2007-2022 Daniel Adler <dadler AT uni-goettingen DOT de>, .\" Tassilo Philipp <tphilipp AT potion-studios DOT com> .\" .\" Permission to use, copy, modify, and distribute this software for any .\" purpose with or without fee is hereby granted, provided that the above .\" copyright notice and this permission notice appear in all copies. .\" .\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES .\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF .\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR .\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES .\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" .Dd $Mdocdate$ .Dt dyncallback 3 .Sh NAME .Nm dyncallback .Nd callback interface of dyncall .Sh SYNOPSIS .In dyncall_callback.h .Ft DCCallback * .Fn dcbNewCallback "const DCsigchar * signature" "DCCallbackHandler * funcptr" "void * userdata" .Ft DCCallback * .Fn dcbNewCallback2 "const DCsigchar * signature" "DCCallbackHandler * funcptr" "void * userdata" "DCaggr *const * aggrs" .Ft void .Fn dcbInitCallback "DCCallback * pcb" "const DCsigchar * signature" "DCCallbackHandler * funcptr" "void * userdata" .Ft void .Fn dcbInitCallback2 "DCCallback * pcb" "const DCsigchar * signature" "DCCallbackHandler * funcptr" "void * userdata" "DCaggr *const * aggrs" .Ft void .Fn dcbFreeCallback "DCCallback * pcb" .Ft void .Fn dcbGetUserData "DCCallback * pcb" .Ft DCbool .Fn dcbArgBool "DCArgs * p" .Ft DCchar .Fn dcbArgChar "DCArgs * p" .Ft DCshort .Fn dcbArgShort "DCArgs * p" .Ft DCint .Fn dcbArgInt "DCArgs * p" .Ft DClong .Fn dcbArgLong "DCArgs * p" .Ft DClonglong .Fn dcbArgLongLong "DCArgs * p" .Ft DCuchar .Fn dcbArgUChar "DCArgs * p" .Ft DCushort .Fn dcbArgUShort "DCArgs * p" .Ft DCuint .Fn dcbArgUInt "DCArgs * p" .Ft DCulong .Fn dcbArgULong "DCArgs * p" .Ft DCulonglong .Fn dcbArgULongLong "DCArgs * p" .Ft DCfloat .Fn dcbArgFloat "DCArgs * p" .Ft DCdouble .Fn dcbArgDouble "DCArgs * p" .Ft DCpointer .Fn dcbArgPointer "DCArgs * p" .Ft DCpointer .Fn dcbArgAggr "DCArgs * p" "DCpointer target" .Ft void .Fn dcbReturnAggr "DCArgs * args" "DCValue * result" "DCpointer ret" .Sh DESCRIPTION The .Nm dyncall library has an interface to create callback objects, that can be passed to functions as callback function pointers. In other words, a pointer to the callback object can be "called", directly. A generic callback handler invoked by this object then allows iterating dynamically over the arguments once called back. .Pp .Fn dcbNewCallback2 creates a new callback object, where .Ar signature is a signature string describing the function to be called back (see manual or dyncall_signature.h for format), and .Ar funcptr is a pointer to a generic callback handler (see below). The signature is needed in the generic callback handler to correctly retrieve the arguments provided by the caller of the callback. Note that the generic handler's function type/declaration is always the same for any callback. .Ar userdata is a pointer to arbitrary user data to be available in the generic callback handler. If the callback expects aggregates (struct, union) to be passed or returned by value, a pointer to an array of DCaggr* descriptions must be provided (exactly one per aggregate, in the same order as in the signature) via the .Ar aggrs parameter, otherwise pass NULL. This pointer must point to valid data during callback. .Pp .Fn dcbNewCallback is the same as .Fn dcbNewCallback2 , with an implicit NULL passed via the .Ar aggrs parameter, meaning it can only be used for callbacks that do not use any aggregate by value. .Pp .Sy NOTE: C++ non-trivial aggregates (check with the std::is_trivial type trait) do not use aggregate descriptions, so the respective pointers in the provided array must be NULL. See .Xr dyncall 3 for more information on C++ non-trivial aggregates. .Pp Use the pointer returned by .Fn dcbNewCallback* as argument in functions requiring a callback function pointer. .Pp .Fn dcbInitCallback and .Fn dcbInitCallback2 (re)initialize the callback object. For a description of their parameters, see .Fn dcbNewCallback* . .Pp .Fn dcbFreeCallback destroys and frees the callback handler. .Pp .Fn dcbGetUserData returns a pointer to the userdata passed to the callback object on creation or (re)initialization. .Pp Declaration of a dyncallback handler (following function pointer declaration in dyncall_callback.h): .Bd -literal -offset indent DCsigchar cbHandler(DCCallback* cb, DCArgs* args, DCValue* result, void* userdata); .Ed .Pp .Ar cb is a pointer to the DCCallback object in use, .Ar args is to be used with the .Fn dcbArg* functions to iterate over the arguments passed to the callback, and .Ar result is a pointer to an object used to store the callback's return value (output, to be set by the handler). Finally, .Ar userdata is the user defined data pointer set when creating or (re)initializing the callback object. The handler itself must return a signature character (see manual or dyncall_signature.h for format) specifying the data type of .Ar result . .Pp Retrieving aggregates by value from the generic handler's .Ar args argument can be done via .Fn dcbArgAggr , where .Ar target must point to memory large enough for the aggregate to be copied to, .Sy iff the aggregate is trivial (see below for non-trivial C++ aggregates), in which case .Ar target is returned. .Pp To return a trivial aggregate by value, a helper function .Fn dcbReturnAggr needs to be used in order to correctly place the aggregate pointed to by .Ar ret into .Ar result , then let the generic handler return DC_SIGCHAR_AGGREGATE. .Pp Retrieving or returning C++ non-trivial aggregates (check with the std::is_trivial type trait) is done differently, as dyncall cannot know how to do this copy and the C++ ABI handles those differently: .Pp When retrieving a C++ non-trivial aggregate via .Fn dcbArgAggr , .Ar target is ignored, and a pointer to the non-trivial aggregate is returned (the user should then do a local copy). To return a C++ non-trivial aggregate by value via .Fn dcbReturnAggr , pass NULL for .Ar ret , which will make .Ar result->p point to (implicit, caller-provided) memory where the aggregate should be copied to. .Sh EXAMPLE Let's say, we want to create a callback object and call it. For simplicity, this example will omit passing it as a function pointer to a function (e.g. compar in qsort(), etc.) and demonstrate calling it, directly. First, we need to define our callback handler - the following handler illustrates how to access the passed- in arguments: .Bd -literal -offset indent DCsigchar cbHandler(DCCallback* cb, DCArgs* args, DCValue* result, void* userdata) { int* ud = (int*)userdata; int arg1 = dcbArgInt (args); float arg2 = dcbArgFloat (args); short arg3 = dcbArgShort (args); double arg4 = dcbArgDouble (args); long long arg5 = dcbArgLongLong(args); /* .. do something .. */ result->s = 1244; return 's'; } .Ed .Pp Note that the return value of the handler is a signature character, not the actual return value, itself. Now, let's call it through a DCCallback object: .Bd -literal -offset indent DCCallback* cb; short result = 0; int userdata = 1337; cb = dcbNewCallback("ifsdl)s", &cbHandler, &userdata); /* call the callback object */ result = ((short(*)(int, float, short, double, long long))cb) (123, 23.f, 3, 1.82, 9909ll); dcbFreeCallback(cb); .Ed .Sh CONFORMING TO The dyncallback 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. .Ed .Sh SEE ALSO .Xr dyncall 3 , .Xr dynload 3 and the dyncall manual (available in HTML and PDF format) for more information. .Sh AUTHORS .An "Daniel Adler" Aq dadler@uni-goettingen.de .An "Tassilo Philipp" Aq tphilipp@potion-studios.com