Mercurial > pub > dyncall > dyncall
comparison test/callback_plain_c++/test_main.cc @ 557:b36a738c8975
- dyncallback: fix for calling back win/x64 C++ methods returning non-trivial aggregates (thanks Raphael!)
- test/callback_plain_c++:
* added test code for C++ method callbacks returning non-trivial aggregates
* makefile linker command fix (was linking assuming c and not c++)
- test/plain_c++: comments for completeness
author | Tassilo Philipp |
---|---|
date | Sat, 20 Aug 2022 21:04:15 +0200 |
parents | 214c4efc104f |
children | 87b5f5d7af1f |
comparison
equal
deleted
inserted
replaced
556:49b60ca068c2 | 557:b36a738c8975 |
---|---|
109 | 109 |
110 | 110 |
111 | 111 |
112 char cbNonTrivAggrReturnHandler(DCCallback* cb, DCArgs* args, DCValue* result, void* userdata) | 112 char cbNonTrivAggrReturnHandler(DCCallback* cb, DCArgs* args, DCValue* result, void* userdata) |
113 { | 113 { |
114 printf("reached callback\n"); | 114 printf("reached callback (for sig \"%s\")\n", *(const char**)userdata); |
115 dcbReturnAggr(args, result, NULL); // this sets result->p to the non-triv aggr space allocated by the calling convention | 115 dcbReturnAggr(args, result, NULL); // this sets result->p to the non-triv aggr space allocated by the calling convention |
116 *(NonTriv*)result->p = NonTriv(1, 3); // explicit non-copy ctor and assignment operator, so not using NonTriv's statics a and b | 116 *(NonTriv*)result->p = NonTriv(1, 3); // explicit non-copy ctor and assignment operator, so not using NonTriv's statics a and b |
117 | 117 |
118 return 'A'; | 118 return 'A'; |
119 } | 119 } |
120 | 120 |
121 | 121 |
122 // class with single vtable entry, used to get the compiler to generate a | |
123 // method call; entry is at beginning w/o offset (see plain_c++/test_main.cc | |
124 // about potential vtable entry offsets) | |
125 struct Dummy { virtual NonTriv f() = 0; }; | |
126 | |
127 | |
122 int testNonTrivAggrReturnCallback() | 128 int testNonTrivAggrReturnCallback() |
123 { | 129 { |
124 int ret = 1; | 130 int ret = 1; |
125 | 131 |
132 const char *sigs[] = { | |
133 ")A", // standard call | |
134 "_*p)A" // thiscall w/ this-ptr arg (special retval register handling in win/x64 calling conv) | |
135 }; | |
136 | |
137 | |
138 for(int i=0; i<sizeof(sigs)/sizeof(sigs[0]); ++i) | |
126 { | 139 { |
127 DCCallback* cb; | 140 int is_method = (sigs[i][0] == '_' && sigs[i][1] == '*'); |
141 | |
128 DCaggr *aggrs[1] = { NULL }; // one non-triv aggr | 142 DCaggr *aggrs[1] = { NULL }; // one non-triv aggr |
129 cb = dcbNewCallback2(")A", &cbNonTrivAggrReturnHandler, NULL, aggrs); | 143 DCCallback* cb = dcbNewCallback2(sigs[i], &cbNonTrivAggrReturnHandler, sigs+i, aggrs); |
130 | 144 |
131 NonTriv result = ((NonTriv(*)())cb)(); // potential copy elision on construction | 145 DCpointer fakeClass[sizeof(Dummy)/sizeof(sizeof(DCpointer))]; |
146 fakeClass[0] = &cb; // write method ptr f | |
147 | |
148 // potential copy elision on construction | |
149 NonTriv result = is_method ? ((Dummy*)&fakeClass)->f() : ((NonTriv(*)())cb)(); | |
132 | 150 |
133 int a = NonTriv::a-1; | 151 int a = NonTriv::a-1; |
134 int b = NonTriv::b-1; | 152 int b = NonTriv::b-1; |
135 printf("successfully returned from callback 1/2\n"); | 153 printf("successfully returned from callback 1/2 of \"%s\"\n", sigs[i]); |
136 printf("retval w/ potential retval optimization and copy-init (should be %d %d for init or %d %d for copy, both allowed by C++): %d %d\n", 1, 3, a, b, result.i, result.j); | 154 printf("retval w/ potential retval optimization and copy-init (should be %d %d for init or %d %d for copy, both allowed by C++): %d %d\n", 1, 3, a, b, result.i, result.j); |
137 | 155 |
138 ret = ((result.i == 1 && result.j == 3) || (result.i == a && result.j == b)) && ret; | 156 ret = ((result.i == 1 && result.j == 3) || (result.i == a && result.j == b)) && ret; |
139 | 157 |
140 // avoid copy elision on construction | 158 // avoid copy elision on construction |
141 result.i = result.j = -77; | 159 result.i = result.j = -77; |
142 result = ((NonTriv(*)())cb)(); // potential copy elision | 160 result = is_method ? ((Dummy*)&fakeClass)->f() : ((NonTriv(*)())cb)(); // potential copy elision |
143 | 161 |
144 a = NonTriv::a-1; | 162 a = NonTriv::a-1; |
145 b = NonTriv::b-1; | 163 b = NonTriv::b-1; |
146 printf("successfully returned from callback 2/2\n"); | 164 printf("successfully returned from callback 2/2 of \"%s\"\n", sigs[i]); |
147 printf("retval w/ potential retval optimization and copy-init (should be %d %d for init or %d %d for copy, both allowed by C++): %d %d\n", 1, 3, a, b, result.i, result.j); | 165 printf("retval w/ potential retval optimization and copy-init (should be %d %d for init or %d %d for copy, both allowed by C++): %d %d\n", 1, 3, a, b, result.i, result.j); |
148 | 166 |
149 dcbFreeCallback(cb); | 167 dcbFreeCallback(cb); |
150 | 168 |
151 ret = ((result.i == 1 && result.j == 3) || (result.i == a && result.j == b)) && ret; | 169 ret = ((result.i == 1 && result.j == 3) || (result.i == a && result.j == b)) && ret; |