changeset 576:53de6e16f445

- more man page examples
author Tassilo Philipp
date Thu, 08 Sep 2022 12:19:51 +0200
parents e5164ef59a6a
children 864cf3c3ceb9
files ChangeLog dyncall/dyncall.3
diffstat 2 files changed, 86 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- 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
--- 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);