Mercurial > pub > dyncall > dyncall
diff dyncall/dyncall.3 @ 533:71c884e610f0
- integration of patches from Raphael Luba, Thekla, Inc.:
* integration of aggregate-by-value (struct, union) support patch for x64 (win and sysv)
* windows/x64 asm additions to specify how stack unwinds (help for debuggers, exception handling, etc.)
* see Changelog for details
- new calling convention modes for thiscalls (platform agnostic, was specific before)
* new signature character for platform agnostic thiscalls ('*' / DC_SIGCHAR_CC_THISCALL)
- dcCallF(), dcVCallF(), dcArgF() and dcVArgF():
* added support for aggregates-by-value (wasn't part of patch)
* change that those functions don't implicitly call dcReset() anymore, which was unflexible (breaking change)
- added macros to feature test implementation for aggregate-by-value and syscall support
- changed libdyncall_s.lib and libdyncallback_s.lib order in callback test makefiles, as some toolchains are picky about order
- doc:
* man page updates to describe aggregate interface
* manual overview changes to highlight platforms with aggregate-by-value support
- test/plain: replaced tests w/ old/stale sctruct interface with new aggregate one
author | Tassilo Philipp |
---|---|
date | Thu, 21 Apr 2022 13:35:47 +0200 |
parents | 78dfa2f9783a |
children | 52e87d4988e3 |
line wrap: on
line diff
--- a/dyncall/dyncall.3 Sat Apr 16 15:00:58 2022 +0200 +++ b/dyncall/dyncall.3 Thu Apr 21 13:35:47 2022 +0200 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2007-2020 Daniel Adler <dadler AT uni-goettingen DOT de>, +.\" 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 @@ -47,6 +47,8 @@ .Fn dcArgDouble "DCCallVM * vm" "DCdouble arg" .Ft void .Fn dcArgPointer "DCCallVM * vm" "DCpointer arg" +.Ft void +.Fn dcArgAggr "DCCallVM * vm" "const DCaggr * ag" "const void * value" .Ft DCvoid .Fn dcCallVoid "DCCallVM * vm" "DCpointer funcptr" .Ft DCbool @@ -67,6 +69,10 @@ .Fn dcCallDouble "DCCallVM * vm" "DCpointer funcptr" .Ft DCpointer .Fn dcCallPointer "DCCallVM * vm" "DCpointer funcptr" +.Ft DCpointer +.Fn dcCallAggr "DCCallVM * vm" "DCpointer funcptr" "const DCaggr * ag" "DCpointer ret" +.Ft void +.Fn dcBeginCallAggr "DCCallVM * vm" "const DCaggr * ag" .Ft void .Fn dcArgF "DCCallVM * vm" "const DCsigchar * signature" "..." .Ft void @@ -75,6 +81,14 @@ .Fn dcCallF "DCCallVM * vm" "DCValue * result" "DCpointer funcptr" "const DCsigchar * signature" "..." .Ft void .Fn dcVCallF "DCCallVM * vm" "DCValue * result" "DCpointer funcptr" "const DCsigchar * signature" "va_list args" +.Ft DCaggr* +.Fn dcNewAggr "DCsize maxFieldCount" "DCsize size" +.Ft void +.Fn dcAggrField "DCaggr* ag" "DCsigchar type" "DCint offset" "DCsize array_len" "..." +.Ft void +.Fn dcCloseAggr "DCaggr* ag" +.Ft void +.Fn dcFreeAggr "DCaggr* ag" .Sh DESCRIPTION The .Nm @@ -95,7 +109,7 @@ that nearly every platform comes with one or more distinct calling conventions, the .Nm 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... +compiler/toolchain/platform-specific binary interfaces subtleties, and so on... .Pp .Fn dcNewCallVM creates a new CallVM object, where @@ -113,13 +127,13 @@ .Pp .Fn 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. +function should be called after setting the initial/main call mode (using +dcMode()), but prior to binding arguments to the CallVM (sometimes dcMode() +calls are needed after pushing some args, e.g. 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. .Pp .Fn dcArgBool , .Fn dcArgChar , @@ -128,9 +142,10 @@ .Fn dcArgLong , .Fn dcArgLongLong , .Fn dcArgFloat , -.Fn dcArgDouble +.Fn dcArgDouble , +.Fn dcArgPointer and -.Fn dcArgPointer +.Fn dcArgAggr are used to bind arguments of the named types to the CallVM object. Arguments should be bound in .Em "left to right" @@ -144,16 +159,61 @@ .Fn dcCallLong , .Fn dcCallLongLong , .Fn dcCallFloat , -.Fn dcCallDouble +.Fn dcCallDouble , +.Fn dcCallPointer and -.Fn dcCallPointer -call the function with the bound arguments and returning the named type, where +.Fn dcCallAggr +call the function with the previously bound arguments and return the named +type, where .Ar 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 -.Fn reset -to clear the internal argument stack. +.Fn dcReset +(as described above) to clear the internal argument stack. +.Pp +The interfaces for passing and/or returning aggregates (struct, union) by value +need to be explained as they are a bit more complex. Every such argument or +return type needs some extra info describing its layout via a +.Ft DCaggr +structure (except for non-trivial C++ aggregates, see AGGREGATE DESCRIPTION for +more information, below). Passing such arguments is then done by using +.Fn dcArgAggr , +where +.Ar ag +is a pointer to the description and +.Ar value +is a pointer to the aggregate in question. Calling a function that returns an +aggregate by value is done via two functions, +.Fn dcBeginCallAggr , +which handles special cases to facilitate the implementation and +.Sy must +be called +.Sy before +pushing any arguments, and finally +.Fn dcCallAggr +where +.Ar ag +is a pointer to the description (for both calls) and +.Ar ret +points to memory large enough to hold the to be returned aggregate. +.Fn dcCallAggr +returns a pointer to +.Ar ret . +.Pp +.Sy NOTE: +C++ non-trivial aggregates (check with the std::is_trivial type trait) need +some special handling. First of all, no aggregate description is needed and +NULL must be passed wherever a +.Ft DCaggr* +argument is needed. Also, as +.Nm +is oblivious to how to do any custom/non-trivial construction or copy, and thus +cannot do the copy of the aggregate, passed by-value, itself, the user has to +provide such copies, where needed. E.g. when passing such an aggregate as an +argument by-value, using +.Fn dcArgAggr , +in order to preserver the call's by-value semantics. .Pp .Fn dcArgF , .Fn dcVArgF , @@ -161,7 +221,7 @@ and .Fn 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 +string encoding the argument and return types. The former 2 only bind the arguments to the .Ar vm object (and ignore return types specified in the @@ -169,9 +229,60 @@ afterwards. The return value will be stored in .Ar result . The signature string also features calling convention mode selection. -For information about the signature format, refer to the +For information about the signature format, refer to dyncall_signature.h or the .Nm -manual in PDF format. +manual. +.Pp +For passing aggregates using +.Fn dc*F +functions, pass two varargs for each aggregate, first a pointer to DCaggr, then +a pointer to the aggregate in question. For returning aggregates using those +functions, pass +.Sy two final extra +arguments, first a pointer to DCaggr describing the return value, then a +pointer to memory large enough to hold it. An explicit call do +.Fn dcBeginCallAggr +is not needed in those cases, and a pointer to the to be returned aggregate is +returned via +.Ar result . +.Sh AGGREGATE DESCRIPTION +In order to describe an aggregate (except for C++ non-trivial aggregates, as +mentioned above), create a DCaggr object using +.Fn dcNewAggr , +where +.Ar maxFieldCount +is greater or equal to the number of fields the aggregate has (a nested +aggregate or an array is counted as one field), and +.Ar size +is the size of the aggregate (e.g. as determined by sizeof()). +.Pp +.Fn dcFreeAggr +destroys the DCaggr object. +.Pp +.Fn dcAggrField +is used to describe the aggregate, field-by-field (in order), with +.Ar type +being a DC_SIGCHAR_* (see dyncall_signature.h), +.Ar offset +being the offset of the field from the beginning of the aggregate (use C's +offsetof(3)), and +.Ar array_len +being the number of array elements, +.Sy iff +the field is an array, otherwise use 1. For nested aggregates (when using +DC_SIGCHAR_AGGREGATE as +.Ft type ) , +one needs to pass the pointer to the nested aggregate's DCaggr object as last +argument (in +.Ar ... ) . +.Pp +Call +.Fn dcCloseAggr +after having described all fields of an aggregate. +.Pp +Note that c99 flexible array members do not count as a field, and must be +omitted, as passing aggregates with a flexible array member by value in C would +also omit it. .Sh EXAMPLE Let's say, we want to make a call to the function: .Bd -literal -offset indent