0
|
1 /*
|
|
2
|
|
3 Package: dyncall
|
|
4 Library: test
|
|
5 File: test/plain_c++/test_main.cc
|
|
6 Description:
|
|
7 License:
|
|
8
|
|
9 Copyright (c) 2007-2015 Daniel Adler <dadler@uni-goettingen.de>,
|
|
10 Tassilo Philipp <tphilipp@potion-studios.com>
|
|
11
|
|
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
|
|
14 copyright notice and this permission notice appear in all copies.
|
|
15
|
|
16 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
17 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
18 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
19 ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
20 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
21 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
22 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
23
|
|
24 */
|
|
25
|
|
26
|
|
27
|
|
28
|
141
|
29 #include "../common/test_framework.h"
|
0
|
30 #include "../../dyncall/dyncall.h"
|
|
31 #include "../common/platformInit.h"
|
|
32 #include "../common/platformInit.c" /* Impl. for functions only used in this translation unit */
|
|
33
|
|
34
|
|
35 /* -------------------------------------------------------------------------
|
|
36 * test: identity function calls
|
|
37 * ------------------------------------------------------------------------- */
|
|
38
|
|
39 #define DEF_FUNCS(API,NAME) \
|
|
40 void API fun_##NAME##_v() { } \
|
|
41 DCbool API fun_##NAME##_b(DCbool x) { return x; } \
|
|
42 DCint API fun_##NAME##_i(DCint x) { return x; } \
|
|
43 DClong API fun_##NAME##_j(DClong x) { return x; } \
|
|
44 DClonglong API fun_##NAME##_l(DClonglong x) { return x; } \
|
|
45 DCfloat API fun_##NAME##_f(DCfloat x) { return x; } \
|
|
46 DCdouble API fun_##NAME##_d(DCdouble x) { return x; } \
|
|
47 DCpointer API fun_##NAME##_p(DCpointer x) { return x; }
|
|
48
|
|
49 /* __cdecl */
|
|
50
|
|
51 #if !defined(DC__OS_Win32)
|
|
52 # define __declspec(X)
|
|
53 # define __cdecl
|
|
54 #endif
|
|
55
|
|
56
|
|
57 /* -------------------------------------------------------------------------
|
|
58 * test: identity this calls
|
|
59 * ------------------------------------------------------------------------- */
|
|
60
|
|
61 union ValueUnion
|
|
62 {
|
|
63 DCbool B;
|
|
64 DCint i;
|
|
65 DClong j;
|
|
66 DClonglong l;
|
|
67 DCfloat f;
|
|
68 DCdouble d;
|
|
69 DCpointer p;
|
|
70 };
|
|
71
|
|
72 /* C++ class using __cdecl this call */
|
|
73
|
|
74 // #define VTBI_DESTRUCTOR 0
|
|
75
|
|
76 /*
|
|
77 * the layout of the VTable is non-standard and it is not clear what is the initial real first method index.
|
|
78 * so for it turns out that:
|
|
79 * on vc/x86 : 1
|
|
80 * on GCC/x86 : 2
|
|
81 */
|
|
82
|
|
83 #if defined DC__C_MSVC
|
|
84 #define VTBI_BASE 1
|
|
85 #else
|
|
86 #define VTBI_BASE 2
|
|
87 #endif
|
|
88
|
|
89 #define VTBI_SET_BOOL VTBI_BASE+0
|
|
90 #define VTBI_GET_BOOL VTBI_BASE+1
|
|
91 #define VTBI_SET_INT VTBI_BASE+2
|
|
92 #define VTBI_GET_INT VTBI_BASE+3
|
|
93 #define VTBI_SET_LONG VTBI_BASE+4
|
|
94 #define VTBI_GET_LONG VTBI_BASE+5
|
|
95 #define VTBI_SET_LONG_LONG VTBI_BASE+6
|
|
96 #define VTBI_GET_LONG_LONG VTBI_BASE+7
|
|
97 #define VTBI_SET_FLOAT VTBI_BASE+8
|
|
98 #define VTBI_GET_FLOAT VTBI_BASE+9
|
|
99 #define VTBI_SET_DOUBLE VTBI_BASE+10
|
|
100 #define VTBI_GET_DOUBLE VTBI_BASE+11
|
|
101 #define VTBI_SET_POINTER VTBI_BASE+12
|
|
102 #define VTBI_GET_POINTER VTBI_BASE+13
|
|
103
|
|
104 class Value
|
|
105 {
|
|
106 public:
|
|
107 virtual ~Value() {}
|
|
108
|
|
109 virtual void __cdecl setBool(DCbool x) { mValue.B = x; }
|
|
110 virtual DCbool __cdecl getBool() { return mValue.B; }
|
|
111 virtual void __cdecl setInt(DCint x) { mValue.i = x; }
|
|
112 virtual DCint __cdecl getInt() { return mValue.i; }
|
|
113 virtual void __cdecl setLong(DClong x) { mValue.j = x; }
|
|
114 virtual DClong __cdecl getLong() { return mValue.j; }
|
|
115 virtual void __cdecl setLongLong(DClonglong x) { mValue.l = x; }
|
|
116 virtual DClonglong __cdecl getLongLong() { return mValue.l; }
|
|
117 virtual void __cdecl setFloat(DCfloat x) { mValue.f = x; }
|
|
118 virtual DCfloat __cdecl getFloat() { return mValue.f; }
|
|
119 virtual void __cdecl setDouble(DCdouble x) { mValue.d = x; }
|
|
120 virtual DCdouble __cdecl getDouble() { return mValue.d; }
|
|
121 virtual void __cdecl setPtr(DCpointer x) { mValue.p = x; }
|
|
122 virtual DCpointer __cdecl getPtr() { return mValue.p; }
|
|
123 private:
|
|
124 ValueUnion mValue;
|
|
125 };
|
|
126
|
|
127 /* C++ class using (on win32: microsoft) this call */
|
|
128
|
|
129 class ValueMS
|
|
130 {
|
|
131 public:
|
|
132 virtual ~ValueMS() {}
|
|
133
|
|
134 virtual void setBool(DCbool x) { mValue.B = x; }
|
|
135 virtual DCbool getBool() { return mValue.B; }
|
|
136 virtual void setInt(DCint x) { mValue.i = x; }
|
|
137 virtual DCint getInt() { return mValue.i; }
|
|
138 virtual void setLong(DClong x) { mValue.j = x; }
|
|
139 virtual DClong getLong() { return mValue.j; }
|
|
140 virtual void setLongLong(DClonglong x) { mValue.l = x; }
|
|
141 virtual DClonglong getLongLong() { return mValue.l; }
|
|
142 virtual void setFloat(DCfloat x) { mValue.f = x; }
|
|
143 virtual DCfloat getFloat() { return mValue.f; }
|
|
144 virtual void setDouble(DCdouble x) { mValue.d = x; }
|
|
145 virtual DCdouble getDouble() { return mValue.d; }
|
|
146 virtual void setPtr(DCpointer x) { mValue.p = x; }
|
|
147 virtual DCpointer getPtr() { return mValue.p; }
|
|
148 private:
|
|
149 ValueUnion mValue;
|
|
150 };
|
|
151
|
|
152 template<typename T>
|
|
153 void testCallValue(DCCallVM* pc)
|
|
154 {
|
|
155 T o;
|
|
156 T* pThis = &o;
|
|
157 DCpointer* vtbl = *( (DCpointer**) pThis ); /* vtbl is located at beginning of class */
|
|
158
|
|
159 /* set/get bool (TRUE) */
|
|
160
|
|
161 dcReset(pc);
|
|
162 dcArgPointer(pc, pThis);
|
|
163 dcArgBool(pc,DC_TRUE);
|
|
164 dcCallVoid(pc, vtbl[VTBI_SET_BOOL] );
|
|
165 dcReset(pc);
|
|
166 dcArgPointer(pc, pThis);
|
|
167 DC_TEST( dcCallBool(pc, vtbl[VTBI_GET_BOOL] ) == DC_TRUE );
|
|
168 /* set/get bool (FALSE) */
|
|
169
|
|
170 dcReset(pc);
|
|
171 dcArgPointer(pc, pThis);
|
|
172 dcArgBool(pc,DC_FALSE);
|
|
173 dcCallVoid(pc, vtbl[VTBI_SET_BOOL] );
|
|
174 dcReset(pc);
|
|
175 dcArgPointer(pc, pThis);
|
|
176 DC_TEST( dcCallBool(pc, vtbl[VTBI_GET_BOOL] ) == DC_FALSE );
|
|
177
|
|
178 /* set/get int */
|
|
179
|
|
180 dcReset(pc);
|
|
181 dcArgPointer(pc, pThis);
|
|
182 dcArgInt(pc,1234);
|
|
183 dcCallVoid(pc, vtbl[VTBI_SET_INT] );
|
|
184 dcReset(pc);
|
|
185 dcArgPointer(pc, pThis);
|
|
186 DC_TEST( dcCallInt(pc, vtbl[VTBI_GET_INT] ) == 1234 );
|
|
187
|
|
188 /* set/get long */
|
|
189
|
|
190 dcReset(pc);
|
|
191 dcArgPointer(pc, pThis);
|
|
192 dcArgLong(pc,0xCAFEBABEUL);
|
|
193 dcCallVoid(pc, vtbl[VTBI_SET_LONG] );
|
|
194 dcReset(pc);
|
|
195 dcArgPointer(pc, pThis);
|
|
196 DC_TEST( dcCallLong(pc, vtbl[VTBI_GET_LONG] ) == (DClong)0xCAFEBABEUL );
|
|
197
|
|
198 /* set/get long long */
|
|
199
|
|
200 dcReset(pc);
|
|
201 dcArgPointer(pc, pThis);
|
|
202 dcArgLongLong(pc,0xCAFEBABEDEADC0DELL);
|
|
203 dcCallVoid(pc, vtbl[VTBI_SET_LONG_LONG] );
|
|
204 dcReset(pc);
|
|
205 dcArgPointer(pc, pThis);
|
|
206 DC_TEST( dcCallLongLong(pc, vtbl[VTBI_GET_LONG_LONG] ) == (DClonglong)0xCAFEBABEDEADC0DELL );
|
|
207
|
|
208 /* set/get float */
|
|
209
|
|
210 dcReset(pc);
|
|
211 dcArgPointer(pc, pThis);
|
|
212 dcArgFloat(pc,1.2345f);
|
|
213 dcCallVoid(pc, vtbl[VTBI_SET_FLOAT] );
|
|
214 dcReset(pc);
|
|
215 dcArgPointer(pc, pThis);
|
|
216 DC_TEST( dcCallFloat(pc, vtbl[VTBI_GET_FLOAT] ) == 1.2345f );
|
|
217
|
|
218 /* set/get double */
|
|
219
|
|
220 dcReset(pc);
|
|
221 dcArgPointer(pc, pThis);
|
|
222 dcArgDouble(pc,1.23456789);
|
|
223 dcCallVoid(pc, vtbl[VTBI_SET_DOUBLE] );
|
|
224 dcReset(pc);
|
|
225 dcArgPointer(pc, pThis);
|
|
226 DC_TEST( dcCallDouble(pc, vtbl[VTBI_GET_DOUBLE] ) == 1.23456789 );
|
|
227
|
|
228 /* set/get pointer */
|
|
229
|
|
230 dcReset(pc);
|
|
231 dcArgPointer(pc, pThis);
|
|
232 dcArgPointer(pc, (DCpointer) 0xCAFEBABE );
|
|
233 dcCallVoid(pc, vtbl[VTBI_SET_POINTER] );
|
|
234 dcReset(pc);
|
|
235 dcArgPointer(pc, pThis);
|
|
236 DC_TEST( dcCallPointer(pc, vtbl[VTBI_GET_POINTER] ) == ( (DCpointer) 0xCAFEBABE ) );
|
|
237 }
|
|
238
|
|
239
|
|
240 #ifdef DC__OS_Win32
|
|
241
|
|
242 DC_DEFINE_TEST_FUNC_BEGIN(testCallThisMS)
|
|
243
|
|
244 DCCallVM* pc = dcNewCallVM(4096);
|
|
245 dcMode(pc,DC_CALL_C_X86_WIN32_THIS_MS);
|
|
246 dcReset(pc);
|
|
247 testCallValue<ValueMS>(pc);
|
|
248 dcFree(pc);
|
|
249
|
|
250 DC_DEFINE_TEST_FUNC_END
|
|
251
|
|
252 #endif
|
|
253
|
|
254
|
|
255 DC_DEFINE_TEST_FUNC_BEGIN(testCallThisC)
|
|
256
|
|
257 DCCallVM* pc = dcNewCallVM(4096);
|
|
258 dcReset(pc);
|
|
259 testCallValue<Value>(pc);
|
|
260 dcFree(pc);
|
|
261
|
|
262 DC_DEFINE_TEST_FUNC_END
|
|
263
|
|
264
|
|
265 extern "C" {
|
|
266
|
|
267 int main(int argc, char* argv[])
|
|
268 {
|
|
269 dcTest_initPlatform();
|
|
270
|
|
271 int b = TRUE;
|
|
272
|
|
273 #if defined(DC__OS_Win32) // ThisCall temporarily only for win 32 @@@
|
|
274
|
|
275 b = b && testCallThisC();
|
|
276 printf("ThisC:%d\n",b);
|
|
277
|
|
278 #if defined(DC__C_MSVC)
|
|
279 b = b && testCallThisMS();
|
|
280 printf("ThisMS:%d\n",b);
|
|
281 #endif
|
|
282
|
|
283 #endif
|
|
284
|
|
285 printf("result: plain_cpp: %d\n", b);
|
|
286
|
|
287 dcTest_deInitPlatform();
|
|
288
|
|
289 return !b;
|
|
290 }
|
|
291
|
|
292 } // extern "C"
|
|
293
|