# HG changeset patch # User Tassilo Philipp # Date 1662632391 -7200 # Node ID 53de6e16f445ec87c9ee1512d66fe27e255f8022 # Parent e5164ef59a6a409fa2961f77b67bc2279652adc5 - more man page examples diff -r e5164ef59a6a -r 53de6e16f445 ChangeLog --- a/ChangeLog Thu Sep 08 11:10:03 2022 +0200 +++ b/ChangeLog Thu Sep 08 12:19:51 2022 +0200 @@ -41,6 +41,7 @@ o new Linux-Std-Base-specific PPC32/SysV section, as aggregate retval handling differs from default SysV for such systems o man page changes/additions to document new aggregate interfaces + o added many more usage examples to man pages o replaced API description in manual with references to the manpages, to avoid duplication and keeping things in sync o general clarifications and cleanup, adding missing definitions to man diff -r e5164ef59a6a -r 53de6e16f445 dyncall/dyncall.3 --- a/dyncall/dyncall.3 Thu Sep 08 11:10:03 2022 +0200 +++ b/dyncall/dyncall.3 Thu Sep 08 12:19:51 2022 +0200 @@ -187,9 +187,9 @@ aggregate by value is done via two functions, .Fn dcBeginCallAggr , which handles special cases to facilitate the implementation and -.Sy must +.Em must be called -.Sy before +.Em before pushing any arguments, and finally .Fn dcCallAggr where @@ -201,7 +201,7 @@ returns a pointer to .Ar ret . .Pp -.Sy NOTE: +.Em 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 @@ -238,7 +238,7 @@ 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 +.Em "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 @@ -268,7 +268,7 @@ offsetof(3)), and .Ar array_len being the number of array elements, -.Sy iff +.Em iff the field is an array, otherwise use 1. For nested aggregates (when using DC_SIGCHAR_AGGREGATE as .Ft type ) , @@ -284,7 +284,8 @@ omitted, as passing aggregates with a flexible array member by value in C would also omit it. .Sh EXAMPLES -Note: none of the examples below perform any error checking for simplicity of +.Em Note : +none of the examples below perform any error checking for simplicity of the example. .Pp Let's start with a simple example, making a call to the function @@ -303,36 +304,106 @@ dcFree(vm); .Ed .Pp -Note that the DCCallVM object can be reused and shouldn't be created and freed -per call, for performance reasons. The following examples will omit creation -and freeing of the DCCallVM, for simplicity. +Note that the +.Sy DCCallVM +object can be reused and shouldn't be created and freed per call, for +performance reasons. The following examples will omit creation and freeing of +the +.Sy DCCallVM , +for simplicity. .Pp In a more complicated example, let's call .Xr printf 3 , which requires a different initial mode, as well as a mode switch for the varargs part: .Bd -literal -offset indent - int n_written_chars, n; + int n_written_chars, r; + /* initial callconv mode */ dcMode(vm, DC_CALL_C_ELLIPSIS); dcReset(vm); /* int printf(const char * restrict format, ...); */ dcArgPointer(vm, "my printf(%d) %s string%n"); + /* switch mode for varargs part */ dcMode(vm, DC_CALL_C_ELLIPSIS_VARARGS); dcArgInt(vm, 3); dcArgPointer(vm, "format"); dcArgPointer(vm, &n_written_chars); - n = dcCallInt(vm, (DCpointer)&printf); + r = dcCallInt(vm, (DCpointer)&printf); +.Ed +.Pp +.Ss C/trivial aggregates by-value +Onto an example passing an aggregate +.Em "by value" +(note that this is only available on platforms where macro +.Dv DC__Feature_AggrByVal +is defined). E.g. passing the following +.Sy struct S +to +.Fn f : +.Bd -literal -offset indent + struct S { char x[3]; double y; }; + void f(int, struct S); .Ed .Pp +requires a +.Sy DCaggr +description of the fields/layout of +.Sy struct S , +and is called as follows: +.Bd -literal -offset indent + struct S s = { { 56, -23, 0 }, -6.28 }; + + DCaggr *a = dcNewAggr(2, sizeof(struct S)); + dcAggrField(a, DC_SIGCHAR_CHAR, offsetof(struct S, x), 3); + dcAggrField(a, DC_SIGCHAR_DOUBLE, offsetof(struct S, y), 1); + dcCloseAggr(a); + + dcMode(vm, DC_CALL_C_DEFAULT); + dcArgInt(vm, 999); + dcArgAggr(vm, a, &s); + + dcCallVoid(vm, (DCpointer)&f); + + dcFreeAggr(a); +.Ed +.Pp +Let's look at an example returning +.Em "by value" +the above +.Sy struct S +from function: +.Bd -literal -offset indent + struct S g(int, short); +.Ed +.Pp +Omitting creation of the +.Sy DCaggr *a +description, for simplicity: +.Bd -literal -offset indent + struct S s; + + dcMode(vm, DC_CALL_C_DEFAULT); + + /* needed when returning aggrs by value, *before* pushing args */ + dcBeginCallAggr(vm, a); + + dcArgInt(vm, 9); + dcArgShort(vm, 7); + + dcCallAggr(vm, (DCpointer)&g, a, &s); +.Ed +.Ss C++ In our next example, let's look at calling a simple C++ method, with the method declaration being: .Bd -literal -offset indent virtual void Klass::Method(float, int); .Ed .Pp -To simplify this example let's assume we have a pointer to this virtual method -in var mptr (grabbed from the instance's vtable), and a pointer to the instance -in var thisptr: +To keep the example simple, let's assume we have a pointer to this virtual +method in var +.Sy mptr +(e.g. grabbed from the instance's vtable), and a pointer to the instance in var +.Sy thisptr : .Bd -literal -offset indent /* thiscall calling convention */ dcMode(vm, DC_CALL_C_DEFAULT_THIS);