diff 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
line wrap: on
line diff
--- a/test/callback_plain/callback_plain.c	Sat Apr 16 15:00:58 2022 +0200
+++ b/test/callback_plain/callback_plain.c	Thu Apr 21 13:35:47 2022 +0200
@@ -6,7 +6,7 @@
  Description: 
  License:
 
-   Copyright (c) 2011-2021 Daniel Adler <dadler@uni-goettingen.de>,
+   Copyright (c) 2011-2022 Daniel Adler <dadler@uni-goettingen.de>,
                            Tassilo Philipp <tphilipp@potion-studios.com>
 
    Permission to use, copy, modify, and distribute this software for any
@@ -28,22 +28,23 @@
 #include "../common/platformInit.c" /* Impl. for functions only used in this translation unit */
 
 
-char cbHandler(DCCallback* cb, DCArgs* args, DCValue* result, void* userdata)
+char cbSimpleHandler(DCCallback* cb, DCArgs* args, DCValue* result, void* userdata)
 {
   int* ud = (int*)userdata;
-  int       arg1 = dcbArgInt     (args);
-  float     arg2 = dcbArgFloat   (args);
-  short     arg3 = dcbArgShort   (args);
-  double    arg4 = dcbArgDouble  (args);
-  long long arg5 = dcbArgLongLong(args);
+  int       arg1;
+  float     arg2;
+  short     arg3;
+  double    arg4;
+  long long arg5;
 
   printf("reached callback\n");
   printf("userdata (should be 1337): %d\n", *ud);
-  printf("1st argument (should be  123): %d\n", arg1);
-  printf("2nd argument (should be 23.f): %f\n", arg2);
-  printf("3rd argument (should be    3): %d\n", arg3);
-  printf("4th argument (should be 1.82): %f\n", arg4);
-  printf("5th argument (should be 9909): %lld\n", arg5);
+
+  arg1 = dcbArgInt     (args);  printf("1st argument (should be  123): %d\n",   arg1);
+  arg2 = dcbArgFloat   (args);  printf("2nd argument (should be 23.f): %f\n",   arg2);
+  arg3 = dcbArgShort   (args);  printf("3rd argument (should be    3): %d\n",   arg3);
+  arg4 = dcbArgDouble  (args);  printf("4th argument (should be 1.82): %f\n",   arg4);
+  arg5 = dcbArgLongLong(args);  printf("5th argument (should be 9909): %lld\n", arg5);
 
   if(*ud == 1337) *ud = 1;
   if(arg1 ==  123) ++*ud;
@@ -56,17 +57,13 @@
   return 's';
 }
 
-
-int main()
+int testSimpleCallback()
 {
   DCCallback* cb;
   short result = 0;
   int userdata = 1337;
 
-  dcTest_initPlatform();
-
-  cb = dcbNewCallback("ifsdl)s", &cbHandler, &userdata);
-  printf("about to callback (trampoline for 0x%tx at 0x%tx)...\n", &cbHandler, cb);
+  cb = dcbNewCallback("ifsdl)s", &cbSimpleHandler, &userdata);
 
   result = ((short(*)(int, float, short, double, long long))cb)(123, 23.f, 3, 1.82, 9909ull);
   dcbFreeCallback(cb);
@@ -74,7 +71,437 @@
   printf("successfully returned from callback\n");
   printf("return value (should be 1234): %d\n", result);
 
-  result = (userdata == 6) && (result == 1234);
+  return (userdata == 6) && (result == 1234);
+}
+
+
+#if defined(DC__Feature_AggrByVal)
+typedef struct {
+  float a;
+  float b;
+} Float_Float;
+
+typedef struct {
+  unsigned char a;
+  double b;
+} U8_Double;
+
+typedef struct {
+  unsigned long long a;
+  unsigned long long b;
+} U64_U64;
+
+typedef struct {
+  double a;
+  double b;
+} Double_Double;
+
+typedef struct {
+  unsigned long long a;
+  unsigned long long b;
+  unsigned long long c;
+} Three_U64;
+
+typedef struct {
+  double a;
+  double b;
+  double c;
+} Three_Double;
+
+
+char cbAggrArgHandler(DCCallback* cb, DCArgs* args, DCValue* result, void* userdata)
+{
+  int* ud = (int*)userdata;
+  int           arg1;
+  Float_Float   arg2;
+  U8_Double     arg3;
+  Three_Double  arg4;
+  double        arg5;
+
+  printf("reached callback\n");
+  printf("userdata: %d\n", *ud);
+
+  arg1 = dcbArgInt(args);                printf("1st argument: %d\n", arg1);
+  dcbArgAggr(args, (DCpointer)&arg2);    printf("2nd argument: %f %f\n", arg2.a, arg2.b);
+  dcbArgAggr(args, (DCpointer)&arg3);    printf("3nd argument: %d %f\n", arg3.a, arg3.b);
+  dcbArgAggr(args, (DCpointer)&arg4);    printf("4rd argument: %f %f %f\n", arg4.a, arg4.b, arg4.c);
+  arg5 = dcbArgDouble(args);             printf("5th argument: %f\n", arg5);
+
+  result->d = *ud + arg1 + arg2.a + arg2.b + arg3.a + arg3.b + arg4.a + arg4.b + arg4.c + arg5;
+  return 'd';
+}
+
+
+int testAggrArgsCallback()
+{
+  DCCallback* cb;
+  DCaggr *float_float_aggr, *u8_double_aggr, *three_double_aggr, *aggrs[3];
+  Float_Float ff;
+  U8_Double u8d;
+  Three_Double threed;
+
+  int ret = 1;
+  double result = 0;
+  int userdata = 1337;
+
+  ff.a = 1.5;
+  ff.b = 5.5;
+  float_float_aggr = dcNewAggr(2, sizeof(ff));
+  dcAggrField(float_float_aggr, DC_SIGCHAR_FLOAT, offsetof(Float_Float, a), 1);
+  dcAggrField(float_float_aggr, DC_SIGCHAR_FLOAT, offsetof(Float_Float, b), 1);
+  dcCloseAggr(float_float_aggr);
+
+  u8d.a = 5;
+  u8d.b = 5.5;
+  u8_double_aggr = dcNewAggr(2, sizeof(u8d));
+  dcAggrField(u8_double_aggr, DC_SIGCHAR_UCHAR,  offsetof(U8_Double, a), 1);
+  dcAggrField(u8_double_aggr, DC_SIGCHAR_DOUBLE, offsetof(U8_Double, b), 1);
+  dcCloseAggr(u8_double_aggr);
+
+  threed.a = 1.5;
+  threed.b = 2.5;
+  threed.c = 3.5;
+  three_double_aggr = dcNewAggr(3, sizeof(threed));
+  dcAggrField(three_double_aggr, DC_SIGCHAR_DOUBLE, offsetof(Three_Double, a), 1);
+  dcAggrField(three_double_aggr, DC_SIGCHAR_DOUBLE, offsetof(Three_Double, b), 1);
+  dcAggrField(three_double_aggr, DC_SIGCHAR_DOUBLE, offsetof(Three_Double, c), 1);
+  dcCloseAggr(three_double_aggr);
+
+  aggrs[0] = float_float_aggr;
+  aggrs[1] = u8_double_aggr;
+  aggrs[2] = three_double_aggr;
+
+  cb = dcbNewCallback2("iAAAd)d", &cbAggrArgHandler, &userdata, aggrs);
+
+  result = ((double(*)(int, Float_Float, U8_Double, Three_Double, double))cb)(123, ff, u8d, threed, 4.5);
+  dcbFreeCallback(cb);
+  dcFreeAggr(float_float_aggr);
+  dcFreeAggr(u8_double_aggr);
+  dcFreeAggr(three_double_aggr);
+
+  printf("successfully returned from callback\n");
+  printf("return value (should be 1489.5): %f\n", result);
+
+  ret = result == 1489.5 && ret;
+
+  return ret;
+}
+
+char cbFloatFloatReturnHandler(DCCallback* cb, DCArgs* args, DCValue* result, void* userdata)
+{
+  int* ud = (int*)userdata;
+  float arg1, arg2;
+  Float_Float ret;
+
+  printf("reached callback\n");
+  printf("userdata: %d\n", *ud);
+
+  arg1 = dcbArgFloat(args);  printf("1st argument: %f\n", arg1);
+  arg2 = dcbArgFloat(args);  printf("2th argument: %f\n", arg2);
+
+  ret.a = *ud + arg1;
+  ret.b = arg2;
+
+  dcbReturnAggr(args, result, (DCpointer)&ret);
+
+  return 't';
+}
+
+char cbU8DoubleReturnHandler(DCCallback* cb, DCArgs* args, DCValue* result, void* userdata)
+{
+  int* ud = (int*)userdata;
+  int arg1;
+  double arg2;
+  U8_Double ret;
+
+  printf("reached callback\n");
+  printf("userdata: %d\n", *ud);
+
+  arg1 = dcbArgInt   (args);  printf("1st argument: %d\n", arg1);
+  arg2 = dcbArgDouble(args);  printf("2th argument: %f\n", arg2);
+
+  ret.a = *ud + arg1;
+  ret.b = arg2;
+
+  dcbReturnAggr(args, result, (DCpointer)&ret);
+
+  return 't';
+}
+
+char cbU64U64ReturnHandler(DCCallback* cb, DCArgs* args, DCValue* result, void* userdata)
+{
+  int* ud = (int*)userdata;
+  unsigned long long arg1, arg2;
+  U64_U64 ret;
+
+  printf("reached callback\n");
+  printf("userdata: %d\n", *ud);
+
+  arg1 = dcbArgULongLong(args);  printf("1st argument: %lld\n", arg1);
+  arg2 = dcbArgULongLong(args);  printf("2th argument: %lld\n", arg2);
+
+  ret.a = *ud + arg1;
+  ret.b = arg2;
+
+  dcbReturnAggr(args, result, (DCpointer)&ret);
+
+  return 't';
+}
+
+char cbDoubleDoubleReturnHandler(DCCallback* cb, DCArgs* args, DCValue* result, void* userdata)
+{
+  int* ud = (int*)userdata;
+  double arg1, arg2;
+  Double_Double ret;
+
+  printf("reached callback\n");
+  printf("userdata: %d\n", *ud);
+
+  arg1 = dcbArgDouble(args);  printf("1st argument: %f\n", arg1);
+  arg2 = dcbArgDouble(args);  printf("2th argument: %f\n", arg2);
+
+  ret.a = *ud + arg1;
+  ret.b = arg2;
+
+  dcbReturnAggr(args, result, (DCpointer)&ret);
+
+  return 't';
+}
+
+char cbThreeU64ReturnHandler(DCCallback* cb, DCArgs* args, DCValue* result, void* userdata)
+{
+  int* ud = (int*)userdata;
+  unsigned long long arg1, arg2, arg3;
+  Three_U64 ret;
+
+  printf("reached callback\n");
+  printf("userdata: %d\n", *ud);
+
+  arg1 = dcbArgULongLong(args);  printf("1st argument: %lld\n", arg1);
+  arg2 = dcbArgULongLong(args);  printf("2th argument: %lld\n", arg2);
+  arg3 = dcbArgULongLong(args);  printf("3th argument: %lld\n", arg3);
+
+  ret.a = *ud + arg1;
+  ret.b = arg2;
+  ret.c = arg3;
+
+  dcbReturnAggr(args, result, (DCpointer)&ret);
+
+  return 't';
+}
+
+char cbThreeDoubleReturnHandler(DCCallback* cb, DCArgs* args, DCValue* result, void* userdata)
+{
+  int* ud = (int*)userdata;
+  double arg1, arg2, arg3;
+  Three_Double ret;
+
+  printf("reached callback\n");
+  printf("userdata: %d\n", *ud);
+
+  arg1 = dcbArgDouble(args);   printf("1st argument: %f\n", arg1);
+  arg2 = dcbArgDouble(args);   printf("2th argument: %f\n", arg2);
+  arg3 = dcbArgDouble(args);   printf("3th argument: %f\n", arg3);
+
+  ret.a = *ud + arg1;
+  ret.b = arg2;
+  ret.c = arg3;
+
+  dcbReturnAggr(args, result, (DCpointer)&ret);
+
+  return 't';
+}
+
+int testAggrReturnCallback()
+{
+  int ret = 1;
+
+  {
+    DCCallback* cb;
+    DCaggr *s;
+    DCaggr *aggrs[1];
+    int userdata = 10;
+    Float_Float expected, result;
+
+    expected.a = 11.5;
+    expected.b = 2.5;
+
+    s = dcNewAggr(2, sizeof(expected));
+    dcAggrField(s, DC_SIGCHAR_FLOAT, offsetof(Float_Float, a), 1);
+    dcAggrField(s, DC_SIGCHAR_FLOAT, offsetof(Float_Float, b), 1);
+    dcCloseAggr(s);
+
+    aggrs[0] = s;
+
+    cb = dcbNewCallback2("ff)A", &cbFloatFloatReturnHandler, &userdata, aggrs);
+
+    result = ((Float_Float(*)(float, float))cb)(1.5, 2.5);
+    dcbFreeCallback(cb);
+    dcFreeAggr(s);
+
+    printf("successfully returned from callback\n");
+    printf("return value (should be %f %f): %f %f\n", expected.a, expected.b, result.a, result.b);
+
+    ret = result.a == expected.a && result.b == expected.b && ret;
+  }
+  {
+    DCCallback* cb;
+    DCaggr *s;
+    DCaggr *aggrs[1];
+    int userdata = 10;
+    U8_Double expected, result;
+
+    expected.a = 15;
+    expected.b = 5.5;
+
+    s = dcNewAggr(2, sizeof(expected));
+    dcAggrField(s, DC_SIGCHAR_UCHAR,  offsetof(U8_Double, a), 1);
+    dcAggrField(s, DC_SIGCHAR_DOUBLE, offsetof(U8_Double, b), 1);
+    dcCloseAggr(s);
+
+    aggrs[0] = s;
+
+    cb = dcbNewCallback2("id)A", &cbU8DoubleReturnHandler, &userdata, aggrs);
+
+    result = ((U8_Double(*)(int, double))cb)(5, 5.5);
+    dcbFreeCallback(cb);
+    dcFreeAggr(s);
+
+    printf("successfully returned from callback\n");
+    printf("return value (should be %d %f): %d %f\n", (int)expected.a, expected.b, (int)result.a, result.b);
+
+    ret = result.a == expected.a && result.b == expected.b && ret;
+  }
+  {
+    DCCallback* cb;
+    DCaggr *s;
+    DCaggr *aggrs[1];
+    int userdata = 10;
+    U64_U64 expected, result;
+
+    expected.a = 35;
+    expected.b = 26;
+    s = dcNewAggr(2, sizeof(expected));
+    dcAggrField(s, DC_SIGCHAR_ULONGLONG, offsetof(U64_U64, a), 1);
+    dcAggrField(s, DC_SIGCHAR_ULONGLONG, offsetof(U64_U64, b), 1);
+    dcCloseAggr(s);
+
+    aggrs[0] = s;
+
+    cb = dcbNewCallback2("LL)A", &cbU64U64ReturnHandler, &userdata, aggrs);
+
+    result = ((U64_U64(*)(unsigned long long, unsigned long long))cb)(25, 26);
+    dcbFreeCallback(cb);
+    dcFreeAggr(s);
+
+    printf("successfully returned from callback\n");
+    printf("return value (should be %lld %lld): %lld %lld\n", expected.a, expected.b, result.a, result.b);
+
+    ret = result.a == expected.a && result.b == expected.b && ret;
+  }
+  {
+    DCCallback* cb;
+    DCaggr *s;
+    DCaggr *aggrs[1];
+    int userdata = 10;
+    Double_Double expected, result;
+
+    expected.a = 11.5;
+    expected.b = 2.5;
+    s = dcNewAggr(2, sizeof(expected));
+    dcAggrField(s, DC_SIGCHAR_DOUBLE, offsetof(Double_Double, a), 1);
+    dcAggrField(s, DC_SIGCHAR_DOUBLE, offsetof(Double_Double, b), 1);
+    dcCloseAggr(s);
+
+    aggrs[0] = s;
+
+    cb = dcbNewCallback2("dd)A", &cbDoubleDoubleReturnHandler, &userdata, aggrs);
+
+    result = ((Double_Double(*)(double, double))cb)(1.5, 2.5);
+    dcbFreeCallback(cb);
+    dcFreeAggr(s);
+
+    printf("successfully returned from callback\n");
+    printf("return value (should be %f %f): %f %f\n", expected.a, expected.b, result.a, result.b);
+
+    ret = result.a == expected.a && result.b == expected.b && ret;
+  }
+  {
+    DCCallback* cb;
+    DCaggr *s;
+    DCaggr *aggrs[1];
+    int userdata = 10;
+    Three_U64 expected, result;
+
+    expected.a = 11;
+    expected.b = 2;
+    expected.c = 3;
+    s = dcNewAggr(3, sizeof(expected));
+    dcAggrField(s, DC_SIGCHAR_ULONGLONG, offsetof(Three_U64, a), 1);
+    dcAggrField(s, DC_SIGCHAR_ULONGLONG, offsetof(Three_U64, b), 1);
+    dcAggrField(s, DC_SIGCHAR_ULONGLONG, offsetof(Three_U64, c), 1);
+    dcCloseAggr(s);
+
+    aggrs[0] = s;
+
+    cb = dcbNewCallback2("LLL)A", &cbThreeU64ReturnHandler, &userdata, aggrs);
+
+    result = ((Three_U64(*)(unsigned long long, unsigned long long, unsigned long long))cb)(1, 2, 3);
+    dcbFreeCallback(cb);
+    dcFreeAggr(s);
+
+    printf("successfully returned from callback\n");
+    printf("return value (should be %lld %lld %lld): %lld %lld %lld\n", expected.a, expected.b, expected.c, result.a, result.b, result.c);
+
+    ret = result.a == expected.a && result.b == expected.b && result.c == expected.c && ret;
+  }
+  {
+    DCCallback* cb;
+    DCaggr *s;
+    DCaggr *aggrs[1];
+    int userdata = 10;
+    Three_Double expected, result;
+
+    expected.a = 11.5;
+    expected.b = 2.5;
+    expected.c = 3.5;
+    s = dcNewAggr(3, sizeof(expected));
+    dcAggrField(s, DC_SIGCHAR_DOUBLE, offsetof(Three_Double, a), 1);
+    dcAggrField(s, DC_SIGCHAR_DOUBLE, offsetof(Three_Double, b), 1);
+    dcAggrField(s, DC_SIGCHAR_DOUBLE, offsetof(Three_Double, c), 1);
+    dcCloseAggr(s);
+
+    aggrs[0] = s;
+
+    cb = dcbNewCallback2("ddd)A", &cbThreeDoubleReturnHandler, &userdata, aggrs);
+
+    result = ((Three_Double(*)(double, double, double))cb)(1.5, 2.5, 3.5);
+    dcbFreeCallback(cb);
+    dcFreeAggr(s);
+
+    printf("successfully returned from callback\n");
+    printf("return value (should be %f %f %f): %f %f %f\n", expected.a, expected.b, expected.c, result.a, result.b, result.c);
+
+    ret = result.a == expected.a && result.b == expected.b && result.c == expected.c && ret;
+  }
+
+  return ret;
+}
+#endif
+
+
+int main()
+{
+  int result = 1;
+
+  dcTest_initPlatform();
+
+  result = testSimpleCallback() && result;
+#if defined(DC__Feature_AggrByVal)
+  result = testAggrArgsCallback() && result;
+  result = testAggrReturnCallback() && result;
+#endif
+
   printf("result: callback_plain: %d\n", result);
 
   dcTest_deInitPlatform();