comparison test/callback_plain/callback_plain.c @ 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 7608e34098b0
children 781b308aa320
comparison
equal deleted inserted replaced
532:d4bf63ab9164 533:71c884e610f0
4 Library: test 4 Library: test
5 File: test/callback_plain/callback_plain.c 5 File: test/callback_plain/callback_plain.c
6 Description: 6 Description:
7 License: 7 License:
8 8
9 Copyright (c) 2011-2021 Daniel Adler <dadler@uni-goettingen.de>, 9 Copyright (c) 2011-2022 Daniel Adler <dadler@uni-goettingen.de>,
10 Tassilo Philipp <tphilipp@potion-studios.com> 10 Tassilo Philipp <tphilipp@potion-studios.com>
11 11
12 Permission to use, copy, modify, and distribute this software for any 12 Permission to use, copy, modify, and distribute this software for any
13 purpose with or without fee is hereby granted, provided that the above 13 purpose with or without fee is hereby granted, provided that the above
14 copyright notice and this permission notice appear in all copies. 14 copyright notice and this permission notice appear in all copies.
26 #include "../../dyncallback/dyncall_callback.h" 26 #include "../../dyncallback/dyncall_callback.h"
27 #include "../common/platformInit.h" 27 #include "../common/platformInit.h"
28 #include "../common/platformInit.c" /* Impl. for functions only used in this translation unit */ 28 #include "../common/platformInit.c" /* Impl. for functions only used in this translation unit */
29 29
30 30
31 char cbHandler(DCCallback* cb, DCArgs* args, DCValue* result, void* userdata) 31 char cbSimpleHandler(DCCallback* cb, DCArgs* args, DCValue* result, void* userdata)
32 { 32 {
33 int* ud = (int*)userdata; 33 int* ud = (int*)userdata;
34 int arg1 = dcbArgInt (args); 34 int arg1;
35 float arg2 = dcbArgFloat (args); 35 float arg2;
36 short arg3 = dcbArgShort (args); 36 short arg3;
37 double arg4 = dcbArgDouble (args); 37 double arg4;
38 long long arg5 = dcbArgLongLong(args); 38 long long arg5;
39 39
40 printf("reached callback\n"); 40 printf("reached callback\n");
41 printf("userdata (should be 1337): %d\n", *ud); 41 printf("userdata (should be 1337): %d\n", *ud);
42 printf("1st argument (should be 123): %d\n", arg1); 42
43 printf("2nd argument (should be 23.f): %f\n", arg2); 43 arg1 = dcbArgInt (args); printf("1st argument (should be 123): %d\n", arg1);
44 printf("3rd argument (should be 3): %d\n", arg3); 44 arg2 = dcbArgFloat (args); printf("2nd argument (should be 23.f): %f\n", arg2);
45 printf("4th argument (should be 1.82): %f\n", arg4); 45 arg3 = dcbArgShort (args); printf("3rd argument (should be 3): %d\n", arg3);
46 printf("5th argument (should be 9909): %lld\n", arg5); 46 arg4 = dcbArgDouble (args); printf("4th argument (should be 1.82): %f\n", arg4);
47 arg5 = dcbArgLongLong(args); printf("5th argument (should be 9909): %lld\n", arg5);
47 48
48 if(*ud == 1337) *ud = 1; 49 if(*ud == 1337) *ud = 1;
49 if(arg1 == 123) ++*ud; 50 if(arg1 == 123) ++*ud;
50 if(arg2 == 23.f) ++*ud; 51 if(arg2 == 23.f) ++*ud;
51 if(arg3 == 3) ++*ud; 52 if(arg3 == 3) ++*ud;
54 55
55 result->s = 1234; 56 result->s = 1234;
56 return 's'; 57 return 's';
57 } 58 }
58 59
59 60 int testSimpleCallback()
60 int main()
61 { 61 {
62 DCCallback* cb; 62 DCCallback* cb;
63 short result = 0; 63 short result = 0;
64 int userdata = 1337; 64 int userdata = 1337;
65 65
66 dcTest_initPlatform(); 66 cb = dcbNewCallback("ifsdl)s", &cbSimpleHandler, &userdata);
67
68 cb = dcbNewCallback("ifsdl)s", &cbHandler, &userdata);
69 printf("about to callback (trampoline for 0x%tx at 0x%tx)...\n", &cbHandler, cb);
70 67
71 result = ((short(*)(int, float, short, double, long long))cb)(123, 23.f, 3, 1.82, 9909ull); 68 result = ((short(*)(int, float, short, double, long long))cb)(123, 23.f, 3, 1.82, 9909ull);
72 dcbFreeCallback(cb); 69 dcbFreeCallback(cb);
73 70
74 printf("successfully returned from callback\n"); 71 printf("successfully returned from callback\n");
75 printf("return value (should be 1234): %d\n", result); 72 printf("return value (should be 1234): %d\n", result);
76 73
77 result = (userdata == 6) && (result == 1234); 74 return (userdata == 6) && (result == 1234);
75 }
76
77
78 #if defined(DC__Feature_AggrByVal)
79 typedef struct {
80 float a;
81 float b;
82 } Float_Float;
83
84 typedef struct {
85 unsigned char a;
86 double b;
87 } U8_Double;
88
89 typedef struct {
90 unsigned long long a;
91 unsigned long long b;
92 } U64_U64;
93
94 typedef struct {
95 double a;
96 double b;
97 } Double_Double;
98
99 typedef struct {
100 unsigned long long a;
101 unsigned long long b;
102 unsigned long long c;
103 } Three_U64;
104
105 typedef struct {
106 double a;
107 double b;
108 double c;
109 } Three_Double;
110
111
112 char cbAggrArgHandler(DCCallback* cb, DCArgs* args, DCValue* result, void* userdata)
113 {
114 int* ud = (int*)userdata;
115 int arg1;
116 Float_Float arg2;
117 U8_Double arg3;
118 Three_Double arg4;
119 double arg5;
120
121 printf("reached callback\n");
122 printf("userdata: %d\n", *ud);
123
124 arg1 = dcbArgInt(args); printf("1st argument: %d\n", arg1);
125 dcbArgAggr(args, (DCpointer)&arg2); printf("2nd argument: %f %f\n", arg2.a, arg2.b);
126 dcbArgAggr(args, (DCpointer)&arg3); printf("3nd argument: %d %f\n", arg3.a, arg3.b);
127 dcbArgAggr(args, (DCpointer)&arg4); printf("4rd argument: %f %f %f\n", arg4.a, arg4.b, arg4.c);
128 arg5 = dcbArgDouble(args); printf("5th argument: %f\n", arg5);
129
130 result->d = *ud + arg1 + arg2.a + arg2.b + arg3.a + arg3.b + arg4.a + arg4.b + arg4.c + arg5;
131 return 'd';
132 }
133
134
135 int testAggrArgsCallback()
136 {
137 DCCallback* cb;
138 DCaggr *float_float_aggr, *u8_double_aggr, *three_double_aggr, *aggrs[3];
139 Float_Float ff;
140 U8_Double u8d;
141 Three_Double threed;
142
143 int ret = 1;
144 double result = 0;
145 int userdata = 1337;
146
147 ff.a = 1.5;
148 ff.b = 5.5;
149 float_float_aggr = dcNewAggr(2, sizeof(ff));
150 dcAggrField(float_float_aggr, DC_SIGCHAR_FLOAT, offsetof(Float_Float, a), 1);
151 dcAggrField(float_float_aggr, DC_SIGCHAR_FLOAT, offsetof(Float_Float, b), 1);
152 dcCloseAggr(float_float_aggr);
153
154 u8d.a = 5;
155 u8d.b = 5.5;
156 u8_double_aggr = dcNewAggr(2, sizeof(u8d));
157 dcAggrField(u8_double_aggr, DC_SIGCHAR_UCHAR, offsetof(U8_Double, a), 1);
158 dcAggrField(u8_double_aggr, DC_SIGCHAR_DOUBLE, offsetof(U8_Double, b), 1);
159 dcCloseAggr(u8_double_aggr);
160
161 threed.a = 1.5;
162 threed.b = 2.5;
163 threed.c = 3.5;
164 three_double_aggr = dcNewAggr(3, sizeof(threed));
165 dcAggrField(three_double_aggr, DC_SIGCHAR_DOUBLE, offsetof(Three_Double, a), 1);
166 dcAggrField(three_double_aggr, DC_SIGCHAR_DOUBLE, offsetof(Three_Double, b), 1);
167 dcAggrField(three_double_aggr, DC_SIGCHAR_DOUBLE, offsetof(Three_Double, c), 1);
168 dcCloseAggr(three_double_aggr);
169
170 aggrs[0] = float_float_aggr;
171 aggrs[1] = u8_double_aggr;
172 aggrs[2] = three_double_aggr;
173
174 cb = dcbNewCallback2("iAAAd)d", &cbAggrArgHandler, &userdata, aggrs);
175
176 result = ((double(*)(int, Float_Float, U8_Double, Three_Double, double))cb)(123, ff, u8d, threed, 4.5);
177 dcbFreeCallback(cb);
178 dcFreeAggr(float_float_aggr);
179 dcFreeAggr(u8_double_aggr);
180 dcFreeAggr(three_double_aggr);
181
182 printf("successfully returned from callback\n");
183 printf("return value (should be 1489.5): %f\n", result);
184
185 ret = result == 1489.5 && ret;
186
187 return ret;
188 }
189
190 char cbFloatFloatReturnHandler(DCCallback* cb, DCArgs* args, DCValue* result, void* userdata)
191 {
192 int* ud = (int*)userdata;
193 float arg1, arg2;
194 Float_Float ret;
195
196 printf("reached callback\n");
197 printf("userdata: %d\n", *ud);
198
199 arg1 = dcbArgFloat(args); printf("1st argument: %f\n", arg1);
200 arg2 = dcbArgFloat(args); printf("2th argument: %f\n", arg2);
201
202 ret.a = *ud + arg1;
203 ret.b = arg2;
204
205 dcbReturnAggr(args, result, (DCpointer)&ret);
206
207 return 't';
208 }
209
210 char cbU8DoubleReturnHandler(DCCallback* cb, DCArgs* args, DCValue* result, void* userdata)
211 {
212 int* ud = (int*)userdata;
213 int arg1;
214 double arg2;
215 U8_Double ret;
216
217 printf("reached callback\n");
218 printf("userdata: %d\n", *ud);
219
220 arg1 = dcbArgInt (args); printf("1st argument: %d\n", arg1);
221 arg2 = dcbArgDouble(args); printf("2th argument: %f\n", arg2);
222
223 ret.a = *ud + arg1;
224 ret.b = arg2;
225
226 dcbReturnAggr(args, result, (DCpointer)&ret);
227
228 return 't';
229 }
230
231 char cbU64U64ReturnHandler(DCCallback* cb, DCArgs* args, DCValue* result, void* userdata)
232 {
233 int* ud = (int*)userdata;
234 unsigned long long arg1, arg2;
235 U64_U64 ret;
236
237 printf("reached callback\n");
238 printf("userdata: %d\n", *ud);
239
240 arg1 = dcbArgULongLong(args); printf("1st argument: %lld\n", arg1);
241 arg2 = dcbArgULongLong(args); printf("2th argument: %lld\n", arg2);
242
243 ret.a = *ud + arg1;
244 ret.b = arg2;
245
246 dcbReturnAggr(args, result, (DCpointer)&ret);
247
248 return 't';
249 }
250
251 char cbDoubleDoubleReturnHandler(DCCallback* cb, DCArgs* args, DCValue* result, void* userdata)
252 {
253 int* ud = (int*)userdata;
254 double arg1, arg2;
255 Double_Double ret;
256
257 printf("reached callback\n");
258 printf("userdata: %d\n", *ud);
259
260 arg1 = dcbArgDouble(args); printf("1st argument: %f\n", arg1);
261 arg2 = dcbArgDouble(args); printf("2th argument: %f\n", arg2);
262
263 ret.a = *ud + arg1;
264 ret.b = arg2;
265
266 dcbReturnAggr(args, result, (DCpointer)&ret);
267
268 return 't';
269 }
270
271 char cbThreeU64ReturnHandler(DCCallback* cb, DCArgs* args, DCValue* result, void* userdata)
272 {
273 int* ud = (int*)userdata;
274 unsigned long long arg1, arg2, arg3;
275 Three_U64 ret;
276
277 printf("reached callback\n");
278 printf("userdata: %d\n", *ud);
279
280 arg1 = dcbArgULongLong(args); printf("1st argument: %lld\n", arg1);
281 arg2 = dcbArgULongLong(args); printf("2th argument: %lld\n", arg2);
282 arg3 = dcbArgULongLong(args); printf("3th argument: %lld\n", arg3);
283
284 ret.a = *ud + arg1;
285 ret.b = arg2;
286 ret.c = arg3;
287
288 dcbReturnAggr(args, result, (DCpointer)&ret);
289
290 return 't';
291 }
292
293 char cbThreeDoubleReturnHandler(DCCallback* cb, DCArgs* args, DCValue* result, void* userdata)
294 {
295 int* ud = (int*)userdata;
296 double arg1, arg2, arg3;
297 Three_Double ret;
298
299 printf("reached callback\n");
300 printf("userdata: %d\n", *ud);
301
302 arg1 = dcbArgDouble(args); printf("1st argument: %f\n", arg1);
303 arg2 = dcbArgDouble(args); printf("2th argument: %f\n", arg2);
304 arg3 = dcbArgDouble(args); printf("3th argument: %f\n", arg3);
305
306 ret.a = *ud + arg1;
307 ret.b = arg2;
308 ret.c = arg3;
309
310 dcbReturnAggr(args, result, (DCpointer)&ret);
311
312 return 't';
313 }
314
315 int testAggrReturnCallback()
316 {
317 int ret = 1;
318
319 {
320 DCCallback* cb;
321 DCaggr *s;
322 DCaggr *aggrs[1];
323 int userdata = 10;
324 Float_Float expected, result;
325
326 expected.a = 11.5;
327 expected.b = 2.5;
328
329 s = dcNewAggr(2, sizeof(expected));
330 dcAggrField(s, DC_SIGCHAR_FLOAT, offsetof(Float_Float, a), 1);
331 dcAggrField(s, DC_SIGCHAR_FLOAT, offsetof(Float_Float, b), 1);
332 dcCloseAggr(s);
333
334 aggrs[0] = s;
335
336 cb = dcbNewCallback2("ff)A", &cbFloatFloatReturnHandler, &userdata, aggrs);
337
338 result = ((Float_Float(*)(float, float))cb)(1.5, 2.5);
339 dcbFreeCallback(cb);
340 dcFreeAggr(s);
341
342 printf("successfully returned from callback\n");
343 printf("return value (should be %f %f): %f %f\n", expected.a, expected.b, result.a, result.b);
344
345 ret = result.a == expected.a && result.b == expected.b && ret;
346 }
347 {
348 DCCallback* cb;
349 DCaggr *s;
350 DCaggr *aggrs[1];
351 int userdata = 10;
352 U8_Double expected, result;
353
354 expected.a = 15;
355 expected.b = 5.5;
356
357 s = dcNewAggr(2, sizeof(expected));
358 dcAggrField(s, DC_SIGCHAR_UCHAR, offsetof(U8_Double, a), 1);
359 dcAggrField(s, DC_SIGCHAR_DOUBLE, offsetof(U8_Double, b), 1);
360 dcCloseAggr(s);
361
362 aggrs[0] = s;
363
364 cb = dcbNewCallback2("id)A", &cbU8DoubleReturnHandler, &userdata, aggrs);
365
366 result = ((U8_Double(*)(int, double))cb)(5, 5.5);
367 dcbFreeCallback(cb);
368 dcFreeAggr(s);
369
370 printf("successfully returned from callback\n");
371 printf("return value (should be %d %f): %d %f\n", (int)expected.a, expected.b, (int)result.a, result.b);
372
373 ret = result.a == expected.a && result.b == expected.b && ret;
374 }
375 {
376 DCCallback* cb;
377 DCaggr *s;
378 DCaggr *aggrs[1];
379 int userdata = 10;
380 U64_U64 expected, result;
381
382 expected.a = 35;
383 expected.b = 26;
384 s = dcNewAggr(2, sizeof(expected));
385 dcAggrField(s, DC_SIGCHAR_ULONGLONG, offsetof(U64_U64, a), 1);
386 dcAggrField(s, DC_SIGCHAR_ULONGLONG, offsetof(U64_U64, b), 1);
387 dcCloseAggr(s);
388
389 aggrs[0] = s;
390
391 cb = dcbNewCallback2("LL)A", &cbU64U64ReturnHandler, &userdata, aggrs);
392
393 result = ((U64_U64(*)(unsigned long long, unsigned long long))cb)(25, 26);
394 dcbFreeCallback(cb);
395 dcFreeAggr(s);
396
397 printf("successfully returned from callback\n");
398 printf("return value (should be %lld %lld): %lld %lld\n", expected.a, expected.b, result.a, result.b);
399
400 ret = result.a == expected.a && result.b == expected.b && ret;
401 }
402 {
403 DCCallback* cb;
404 DCaggr *s;
405 DCaggr *aggrs[1];
406 int userdata = 10;
407 Double_Double expected, result;
408
409 expected.a = 11.5;
410 expected.b = 2.5;
411 s = dcNewAggr(2, sizeof(expected));
412 dcAggrField(s, DC_SIGCHAR_DOUBLE, offsetof(Double_Double, a), 1);
413 dcAggrField(s, DC_SIGCHAR_DOUBLE, offsetof(Double_Double, b), 1);
414 dcCloseAggr(s);
415
416 aggrs[0] = s;
417
418 cb = dcbNewCallback2("dd)A", &cbDoubleDoubleReturnHandler, &userdata, aggrs);
419
420 result = ((Double_Double(*)(double, double))cb)(1.5, 2.5);
421 dcbFreeCallback(cb);
422 dcFreeAggr(s);
423
424 printf("successfully returned from callback\n");
425 printf("return value (should be %f %f): %f %f\n", expected.a, expected.b, result.a, result.b);
426
427 ret = result.a == expected.a && result.b == expected.b && ret;
428 }
429 {
430 DCCallback* cb;
431 DCaggr *s;
432 DCaggr *aggrs[1];
433 int userdata = 10;
434 Three_U64 expected, result;
435
436 expected.a = 11;
437 expected.b = 2;
438 expected.c = 3;
439 s = dcNewAggr(3, sizeof(expected));
440 dcAggrField(s, DC_SIGCHAR_ULONGLONG, offsetof(Three_U64, a), 1);
441 dcAggrField(s, DC_SIGCHAR_ULONGLONG, offsetof(Three_U64, b), 1);
442 dcAggrField(s, DC_SIGCHAR_ULONGLONG, offsetof(Three_U64, c), 1);
443 dcCloseAggr(s);
444
445 aggrs[0] = s;
446
447 cb = dcbNewCallback2("LLL)A", &cbThreeU64ReturnHandler, &userdata, aggrs);
448
449 result = ((Three_U64(*)(unsigned long long, unsigned long long, unsigned long long))cb)(1, 2, 3);
450 dcbFreeCallback(cb);
451 dcFreeAggr(s);
452
453 printf("successfully returned from callback\n");
454 printf("return value (should be %lld %lld %lld): %lld %lld %lld\n", expected.a, expected.b, expected.c, result.a, result.b, result.c);
455
456 ret = result.a == expected.a && result.b == expected.b && result.c == expected.c && ret;
457 }
458 {
459 DCCallback* cb;
460 DCaggr *s;
461 DCaggr *aggrs[1];
462 int userdata = 10;
463 Three_Double expected, result;
464
465 expected.a = 11.5;
466 expected.b = 2.5;
467 expected.c = 3.5;
468 s = dcNewAggr(3, sizeof(expected));
469 dcAggrField(s, DC_SIGCHAR_DOUBLE, offsetof(Three_Double, a), 1);
470 dcAggrField(s, DC_SIGCHAR_DOUBLE, offsetof(Three_Double, b), 1);
471 dcAggrField(s, DC_SIGCHAR_DOUBLE, offsetof(Three_Double, c), 1);
472 dcCloseAggr(s);
473
474 aggrs[0] = s;
475
476 cb = dcbNewCallback2("ddd)A", &cbThreeDoubleReturnHandler, &userdata, aggrs);
477
478 result = ((Three_Double(*)(double, double, double))cb)(1.5, 2.5, 3.5);
479 dcbFreeCallback(cb);
480 dcFreeAggr(s);
481
482 printf("successfully returned from callback\n");
483 printf("return value (should be %f %f %f): %f %f %f\n", expected.a, expected.b, expected.c, result.a, result.b, result.c);
484
485 ret = result.a == expected.a && result.b == expected.b && result.c == expected.c && ret;
486 }
487
488 return ret;
489 }
490 #endif
491
492
493 int main()
494 {
495 int result = 1;
496
497 dcTest_initPlatform();
498
499 result = testSimpleCallback() && result;
500 #if defined(DC__Feature_AggrByVal)
501 result = testAggrArgsCallback() && result;
502 result = testAggrReturnCallback() && result;
503 #endif
504
78 printf("result: callback_plain: %d\n", result); 505 printf("result: callback_plain: %d\n", result);
79 506
80 dcTest_deInitPlatform(); 507 dcTest_deInitPlatform();
81 508
82 return !result; 509 return !result;