Mercurial > pub > dyncall > dyncall
comparison 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 |
comparison
equal
deleted
inserted
replaced
532:d4bf63ab9164 | 533:71c884e610f0 |
---|---|
1 .\" Copyright (c) 2007-2020 Daniel Adler <dadler AT uni-goettingen DOT de>, | 1 .\" Copyright (c) 2007-2022 Daniel Adler <dadler AT uni-goettingen DOT de>, |
2 .\" Tassilo Philipp <tphilipp AT potion-studios DOT com> | 2 .\" Tassilo Philipp <tphilipp AT potion-studios DOT com> |
3 .\" | 3 .\" |
4 .\" Permission to use, copy, modify, and distribute this software for any | 4 .\" Permission to use, copy, modify, and distribute this software for any |
5 .\" purpose with or without fee is hereby granted, provided that the above | 5 .\" purpose with or without fee is hereby granted, provided that the above |
6 .\" copyright notice and this permission notice appear in all copies. | 6 .\" copyright notice and this permission notice appear in all copies. |
45 .Fn dcArgFloat "DCCallVM * vm" "DCfloat arg" | 45 .Fn dcArgFloat "DCCallVM * vm" "DCfloat arg" |
46 .Ft void | 46 .Ft void |
47 .Fn dcArgDouble "DCCallVM * vm" "DCdouble arg" | 47 .Fn dcArgDouble "DCCallVM * vm" "DCdouble arg" |
48 .Ft void | 48 .Ft void |
49 .Fn dcArgPointer "DCCallVM * vm" "DCpointer arg" | 49 .Fn dcArgPointer "DCCallVM * vm" "DCpointer arg" |
50 .Ft void | |
51 .Fn dcArgAggr "DCCallVM * vm" "const DCaggr * ag" "const void * value" | |
50 .Ft DCvoid | 52 .Ft DCvoid |
51 .Fn dcCallVoid "DCCallVM * vm" "DCpointer funcptr" | 53 .Fn dcCallVoid "DCCallVM * vm" "DCpointer funcptr" |
52 .Ft DCbool | 54 .Ft DCbool |
53 .Fn dcCallBool "DCCallVM * vm" "DCpointer funcptr" | 55 .Fn dcCallBool "DCCallVM * vm" "DCpointer funcptr" |
54 .Ft DCchar | 56 .Ft DCchar |
65 .Fn dcCallFloat "DCCallVM * vm" "DCpointer funcptr" | 67 .Fn dcCallFloat "DCCallVM * vm" "DCpointer funcptr" |
66 .Ft DCdouble | 68 .Ft DCdouble |
67 .Fn dcCallDouble "DCCallVM * vm" "DCpointer funcptr" | 69 .Fn dcCallDouble "DCCallVM * vm" "DCpointer funcptr" |
68 .Ft DCpointer | 70 .Ft DCpointer |
69 .Fn dcCallPointer "DCCallVM * vm" "DCpointer funcptr" | 71 .Fn dcCallPointer "DCCallVM * vm" "DCpointer funcptr" |
72 .Ft DCpointer | |
73 .Fn dcCallAggr "DCCallVM * vm" "DCpointer funcptr" "const DCaggr * ag" "DCpointer ret" | |
74 .Ft void | |
75 .Fn dcBeginCallAggr "DCCallVM * vm" "const DCaggr * ag" | |
70 .Ft void | 76 .Ft void |
71 .Fn dcArgF "DCCallVM * vm" "const DCsigchar * signature" "..." | 77 .Fn dcArgF "DCCallVM * vm" "const DCsigchar * signature" "..." |
72 .Ft void | 78 .Ft void |
73 .Fn dcVArgF "DCCallVM * vm" "const DCsigchar * signature" "va_list args" | 79 .Fn dcVArgF "DCCallVM * vm" "const DCsigchar * signature" "va_list args" |
74 .Ft void | 80 .Ft void |
75 .Fn dcCallF "DCCallVM * vm" "DCValue * result" "DCpointer funcptr" "const DCsigchar * signature" "..." | 81 .Fn dcCallF "DCCallVM * vm" "DCValue * result" "DCpointer funcptr" "const DCsigchar * signature" "..." |
76 .Ft void | 82 .Ft void |
77 .Fn dcVCallF "DCCallVM * vm" "DCValue * result" "DCpointer funcptr" "const DCsigchar * signature" "va_list args" | 83 .Fn dcVCallF "DCCallVM * vm" "DCValue * result" "DCpointer funcptr" "const DCsigchar * signature" "va_list args" |
84 .Ft DCaggr* | |
85 .Fn dcNewAggr "DCsize maxFieldCount" "DCsize size" | |
86 .Ft void | |
87 .Fn dcAggrField "DCaggr* ag" "DCsigchar type" "DCint offset" "DCsize array_len" "..." | |
88 .Ft void | |
89 .Fn dcCloseAggr "DCaggr* ag" | |
90 .Ft void | |
91 .Fn dcFreeAggr "DCaggr* ag" | |
78 .Sh DESCRIPTION | 92 .Sh DESCRIPTION |
79 The | 93 The |
80 .Nm | 94 .Nm |
81 library encapsulates architecture-, OS- and compiler-specific function call | 95 library encapsulates architecture-, OS- and compiler-specific function call |
82 semantics in a virtual "bind argument parameters from left to right and then | 96 semantics in a virtual "bind argument parameters from left to right and then |
93 and then used to actually invoke the call, is called CallVM. It is possible to | 107 and then used to actually invoke the call, is called CallVM. It is possible to |
94 change the calling convention used by the CallVM at run-time. Due to the fact | 108 change the calling convention used by the CallVM at run-time. Due to the fact |
95 that nearly every platform comes with one or more distinct calling conventions, the | 109 that nearly every platform comes with one or more distinct calling conventions, the |
96 .Nm | 110 .Nm |
97 library project intends to be a portable and open-source approach to the variety of | 111 library project intends to be a portable and open-source approach to the variety of |
98 compiler-specific binary interfaces, platform specific subtleties, and so on... | 112 compiler/toolchain/platform-specific binary interfaces subtleties, and so on... |
99 .Pp | 113 .Pp |
100 .Fn dcNewCallVM | 114 .Fn dcNewCallVM |
101 creates a new CallVM object, where | 115 creates a new CallVM object, where |
102 .Ar size | 116 .Ar size |
103 specifies the max size of the internal stack that will be allocated and used to | 117 specifies the max size of the internal stack that will be allocated and used to |
111 sense (e.g. using a PowerPC calling convention on a MIPS platform) and are | 125 sense (e.g. using a PowerPC calling convention on a MIPS platform) and are |
112 silently ignored. | 126 silently ignored. |
113 .Pp | 127 .Pp |
114 .Fn dcReset | 128 .Fn dcReset |
115 resets the internal stack of arguments and prepares it for a new call. This | 129 resets the internal stack of arguments and prepares it for a new call. This |
116 function should be called after setting the call mode (using dcMode), but prior | 130 function should be called after setting the initial/main call mode (using |
117 to binding arguments to the CallVM (except for when setting mode | 131 dcMode()), but prior to binding arguments to the CallVM (sometimes dcMode() |
118 DC_SIGCHAR_CC_ELLIPSIS_VARARGS, which is used prior to binding varargs of | 132 calls are needed after pushing some args, e.g. DC_SIGCHAR_CC_ELLIPSIS_VARARGS, |
119 variadic functions). Use it also when reusing a CallVM, as arguments don't get | 133 which is used prior to binding varargs of variadic functions). Use it also when |
120 flushed automatically after a function call invocation. Note: you should also | 134 reusing a CallVM, as arguments don't get flushed automatically after a function |
121 call this function after initial creation of the a CallVM object, as | 135 call invocation. Note: you should also call this function after initial |
122 dcNewCallVM doesn't do this, implicitly. | 136 creation of the a CallVM object, as dcNewCallVM doesn't do this, implicitly. |
123 .Pp | 137 .Pp |
124 .Fn dcArgBool , | 138 .Fn dcArgBool , |
125 .Fn dcArgChar , | 139 .Fn dcArgChar , |
126 .Fn dcArgShort , | 140 .Fn dcArgShort , |
127 .Fn dcArgInt , | 141 .Fn dcArgInt , |
128 .Fn dcArgLong , | 142 .Fn dcArgLong , |
129 .Fn dcArgLongLong , | 143 .Fn dcArgLongLong , |
130 .Fn dcArgFloat , | 144 .Fn dcArgFloat , |
131 .Fn dcArgDouble | 145 .Fn dcArgDouble , |
146 .Fn dcArgPointer | |
132 and | 147 and |
133 .Fn dcArgPointer | 148 .Fn dcArgAggr |
134 are used to bind arguments of the named types to the CallVM object. Arguments should | 149 are used to bind arguments of the named types to the CallVM object. Arguments should |
135 be bound in | 150 be bound in |
136 .Em "left to right" | 151 .Em "left to right" |
137 order regarding the C function prototype. | 152 order regarding the C function prototype. |
138 .Pp | 153 .Pp |
142 .Fn dcCallShort , | 157 .Fn dcCallShort , |
143 .Fn dcCallInt , | 158 .Fn dcCallInt , |
144 .Fn dcCallLong , | 159 .Fn dcCallLong , |
145 .Fn dcCallLongLong , | 160 .Fn dcCallLongLong , |
146 .Fn dcCallFloat , | 161 .Fn dcCallFloat , |
147 .Fn dcCallDouble | 162 .Fn dcCallDouble , |
163 .Fn dcCallPointer | |
148 and | 164 and |
149 .Fn dcCallPointer | 165 .Fn dcCallAggr |
150 call the function with the bound arguments and returning the named type, where | 166 call the function with the previously bound arguments and return the named |
167 type, where | |
151 .Ar funcptr | 168 .Ar funcptr |
152 is a pointer to the function to call. After the invocation of the function | 169 is a pointer to the function to call. After the invocation of the function |
153 call, the argument values are still bound to the CallVM and a second call | 170 call, the argument values are still bound to the CallVM and a second call |
154 using the same arguments can be issued. Call | 171 using the same arguments can be issued. Call |
155 .Fn reset | 172 .Fn dcReset |
156 to clear the internal argument stack. | 173 (as described above) to clear the internal argument stack. |
174 .Pp | |
175 The interfaces for passing and/or returning aggregates (struct, union) by value | |
176 need to be explained as they are a bit more complex. Every such argument or | |
177 return type needs some extra info describing its layout via a | |
178 .Ft DCaggr | |
179 structure (except for non-trivial C++ aggregates, see AGGREGATE DESCRIPTION for | |
180 more information, below). Passing such arguments is then done by using | |
181 .Fn dcArgAggr , | |
182 where | |
183 .Ar ag | |
184 is a pointer to the description and | |
185 .Ar value | |
186 is a pointer to the aggregate in question. Calling a function that returns an | |
187 aggregate by value is done via two functions, | |
188 .Fn dcBeginCallAggr , | |
189 which handles special cases to facilitate the implementation and | |
190 .Sy must | |
191 be called | |
192 .Sy before | |
193 pushing any arguments, and finally | |
194 .Fn dcCallAggr | |
195 where | |
196 .Ar ag | |
197 is a pointer to the description (for both calls) and | |
198 .Ar ret | |
199 points to memory large enough to hold the to be returned aggregate. | |
200 .Fn dcCallAggr | |
201 returns a pointer to | |
202 .Ar ret . | |
203 .Pp | |
204 .Sy NOTE: | |
205 C++ non-trivial aggregates (check with the std::is_trivial type trait) need | |
206 some special handling. First of all, no aggregate description is needed and | |
207 NULL must be passed wherever a | |
208 .Ft DCaggr* | |
209 argument is needed. Also, as | |
210 .Nm | |
211 is oblivious to how to do any custom/non-trivial construction or copy, and thus | |
212 cannot do the copy of the aggregate, passed by-value, itself, the user has to | |
213 provide such copies, where needed. E.g. when passing such an aggregate as an | |
214 argument by-value, using | |
215 .Fn dcArgAggr , | |
216 in order to preserver the call's by-value semantics. | |
157 .Pp | 217 .Pp |
158 .Fn dcArgF , | 218 .Fn dcArgF , |
159 .Fn dcVArgF , | 219 .Fn dcVArgF , |
160 .Fn dcCallF | 220 .Fn dcCallF |
161 and | 221 and |
162 .Fn dcVCallF | 222 .Fn dcVCallF |
163 can be used to bind arguments in a printf-style call, using a signature | 223 can be used to bind arguments in a printf-style call, using a signature |
164 string encoding the argument types and return type. The former 2 only bind | 224 string encoding the argument and return types. The former 2 only bind |
165 the arguments to the | 225 the arguments to the |
166 .Ar vm | 226 .Ar vm |
167 object (and ignore return types specified in the | 227 object (and ignore return types specified in the |
168 signature), whereas the latter two issue a call to the given function pointer, | 228 signature), whereas the latter two issue a call to the given function pointer, |
169 afterwards. The return value will be stored in | 229 afterwards. The return value will be stored in |
170 .Ar result . | 230 .Ar result . |
171 The signature string also features calling convention mode selection. | 231 The signature string also features calling convention mode selection. |
172 For information about the signature format, refer to the | 232 For information about the signature format, refer to dyncall_signature.h or the |
173 .Nm | 233 .Nm |
174 manual in PDF format. | 234 manual. |
235 .Pp | |
236 For passing aggregates using | |
237 .Fn dc*F | |
238 functions, pass two varargs for each aggregate, first a pointer to DCaggr, then | |
239 a pointer to the aggregate in question. For returning aggregates using those | |
240 functions, pass | |
241 .Sy two final extra | |
242 arguments, first a pointer to DCaggr describing the return value, then a | |
243 pointer to memory large enough to hold it. An explicit call do | |
244 .Fn dcBeginCallAggr | |
245 is not needed in those cases, and a pointer to the to be returned aggregate is | |
246 returned via | |
247 .Ar result . | |
248 .Sh AGGREGATE DESCRIPTION | |
249 In order to describe an aggregate (except for C++ non-trivial aggregates, as | |
250 mentioned above), create a DCaggr object using | |
251 .Fn dcNewAggr , | |
252 where | |
253 .Ar maxFieldCount | |
254 is greater or equal to the number of fields the aggregate has (a nested | |
255 aggregate or an array is counted as one field), and | |
256 .Ar size | |
257 is the size of the aggregate (e.g. as determined by sizeof()). | |
258 .Pp | |
259 .Fn dcFreeAggr | |
260 destroys the DCaggr object. | |
261 .Pp | |
262 .Fn dcAggrField | |
263 is used to describe the aggregate, field-by-field (in order), with | |
264 .Ar type | |
265 being a DC_SIGCHAR_* (see dyncall_signature.h), | |
266 .Ar offset | |
267 being the offset of the field from the beginning of the aggregate (use C's | |
268 offsetof(3)), and | |
269 .Ar array_len | |
270 being the number of array elements, | |
271 .Sy iff | |
272 the field is an array, otherwise use 1. For nested aggregates (when using | |
273 DC_SIGCHAR_AGGREGATE as | |
274 .Ft type ) , | |
275 one needs to pass the pointer to the nested aggregate's DCaggr object as last | |
276 argument (in | |
277 .Ar ... ) . | |
278 .Pp | |
279 Call | |
280 .Fn dcCloseAggr | |
281 after having described all fields of an aggregate. | |
282 .Pp | |
283 Note that c99 flexible array members do not count as a field, and must be | |
284 omitted, as passing aggregates with a flexible array member by value in C would | |
285 also omit it. | |
175 .Sh EXAMPLE | 286 .Sh EXAMPLE |
176 Let's say, we want to make a call to the function: | 287 Let's say, we want to make a call to the function: |
177 .Bd -literal -offset indent | 288 .Bd -literal -offset indent |
178 double sqrt(double x); | 289 double sqrt(double x); |
179 .Ed | 290 .Ed |