1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4
5#include <stdio.h>
6#include <string.h>
7
8#if defined(__clang__)
9#define EXPORT(type) __attribute__((visibility("default"))) extern "C" type
10#elif defined(_MSC_VER)
11#define EXPORT(type) extern "C" __declspec(dllexport) type
12#else // defined(__clang__)
13#define EXPORT(type) type
14#endif // !defined(__clang__)
15
16#if !defined(_MSC_VER)
17#if __i386__
18#define __stdcall __attribute__((stdcall))
19#else // __i386__
20#define __stdcall
21#endif // !__i386__
22#endif // !defined(_MSC_VER)
23
24#ifndef _countof
25#define _countof(_array) (sizeof(_array)/sizeof(_array[0]))
26#endif
27
28#ifdef _MSC_VER
29#define CALLBACK __stdcall
30#else // _MSC_VER
31#define CALLBACK
32#endif // !_MSC_VER
33
34typedef struct _Vector3
35{
36 float x;
37 float y;
38 float z;
39} Vector3;
40
41typedef struct _DT
42{
43 Vector3 a;
44 Vector3 b;
45} DT;
46
47typedef struct _ComplexDT
48{
49 int iv;
50 DT vecs;
51 char str[256];
52 Vector3 v3;
53} ComplexDT;
54
55//
56// PInvoke native call for Vector3 size check
57//
58
59EXPORT(int) __stdcall nativeCall_PInvoke_CheckVector3Size()
60{
61 printf("nativeCall_PInvoke_CheckVector3Size: sizeof(Vector3) == %d\n", (int)sizeof(Vector3));
62 fflush(stdout);
63 return sizeof(Vector3);
64}
65
66//
67// PInvoke native call for Vector3 argument
68//
69
70EXPORT(float) __stdcall nativeCall_PInvoke_Vector3Arg(int i, Vector3 v1, char* s, Vector3 v2)
71{
72 float sum0 = v1.x + v1.y + v1.z;
73 float sum1 = v2.x + v2.y + v2.z;
74 printf("nativeCall_PInvoke_Vector3Arg:\n");
75 printf(" iVal %d\n", i);
76 printf(" sumOfEles(%f, %f, %f) = %f\n", v1.x, v1.y, v1.z, sum0);
77 printf(" str %s\n", s);
78 printf(" sumOfEles(%f, %f, %f) = %f\n", v2.x, v2.y, v2.z, sum1);
79 fflush(stdout);
80 if ((strncmp(s, "abcdefg", strnlen(s, 32)) != 0) || i != 123) {
81 return 0;
82 }
83 return sum0 + sum1;
84}
85
86//
87// PInvoke native call for Vector3 argument
88//
89EXPORT(float) __stdcall nativeCall_PInvoke_Vector3Arg_Unix(
90 Vector3 v3f32_xmm0,
91 float f32_xmm2,
92 float f32_xmm3,
93 float f32_xmm4,
94 float f32_xmm5,
95 float f32_xmm6,
96 float f32_xmm7,
97 float f32_mem0,
98 Vector3 v3f32_mem1,
99 float f32_mem2,
100 float f32_mem3)
101{
102 printf("nativeCall_PInvoke_Vector3Arg_Unix:\n");
103 printf(" v3f32_xmm0: %f %f %f\n", v3f32_xmm0.x, v3f32_xmm0.y, v3f32_xmm0.z);
104 printf(" f32_xmm2 - f32_xmm7: %f %f %f %f %f %f\n", f32_xmm2, f32_xmm3,
105 f32_xmm4, f32_xmm5, f32_xmm6, f32_xmm7);
106 printf(" f32_mem0: %f\n", f32_mem0);
107 printf(" v3f32_mem1: %f %f %f\n", v3f32_mem1.x, v3f32_mem1.y, v3f32_mem1.z);
108 printf(" f32_mem2-3: %f %f\n", f32_mem2, f32_mem3);
109
110 // sum = 1 + 2 + 3
111 // + 100 + 101 + 102 + 103 + 104 + 105 + 106
112 // + 10 + 20 + 30
113 // + 107 + 108
114 // = 1002
115 float sum = v3f32_xmm0.x + v3f32_xmm0.y + v3f32_xmm0.z
116 + f32_xmm2 + f32_xmm3 + f32_xmm4 + f32_xmm5 + f32_xmm6 + f32_xmm7 + f32_mem0 +
117 + v3f32_mem1.x + v3f32_mem1.y + v3f32_mem1.z
118 + f32_mem2 + f32_mem3;
119
120 printf(" sum = %f\n", sum);
121
122 return sum;
123}
124
125
126//
127// PInvoke native call for Vector3 argument
128//
129EXPORT(float) __stdcall nativeCall_PInvoke_Vector3Arg_Unix2(
130 Vector3 v3f32_xmm0,
131 float f32_xmm2,
132 float f32_xmm3,
133 float f32_xmm4,
134 float f32_xmm5,
135 float f32_xmm6,
136 float f32_xmm7,
137 float f32_mem0,
138 Vector3 v3f32_mem1,
139 float f32_mem2,
140 float f32_mem3,
141 Vector3 v3f32_mem4,
142 float f32_mem5)
143{
144 printf("nativeCall_PInvoke_Vector3Arg_Unix2:\n");
145 printf(" v3f32_xmm0: %f %f %f\n", v3f32_xmm0.x, v3f32_xmm0.y, v3f32_xmm0.z);
146 printf(" f32_xmm2 - f32_xmm7: %f %f %f %f %f %f\n",
147 f32_xmm2, f32_xmm3, f32_xmm4, f32_xmm5, f32_xmm6, f32_xmm7);
148 printf(" f32_mem0: %f\n", f32_mem0);
149 printf(" v3f32_mem1: %f %f %f\n", v3f32_mem1.x, v3f32_mem1.y, v3f32_mem1.z);
150 printf(" f32_mem2-3: %f %f\n", f32_mem2, f32_mem3);
151 printf(" v3f32_mem4: %f %f %f\n", v3f32_mem4.x, v3f32_mem4.y, v3f32_mem4.z);
152 printf(" f32_mem5: %f\n", f32_mem5);
153
154 // sum = 1 + 2 + 3 +
155 // + 100 + 101 + 102 + 103 + 104 + 105 + 106
156 // + 4 + 5 + 6
157 // + 107 + 108
158 // + 7 + 8 + 9
159 // + 109
160 // = 6 + 15 + 24 + 1045 = 1090
161 float sum = v3f32_xmm0.x + v3f32_xmm0.y + v3f32_xmm0.z
162 + f32_xmm2 + f32_xmm3 + f32_xmm4 + f32_xmm5 + f32_xmm6 + f32_xmm7 + f32_mem0 +
163 + v3f32_mem1.x + v3f32_mem1.y + v3f32_mem1.z
164 + f32_mem2 + f32_mem3
165 + v3f32_mem4.x + v3f32_mem4.y + v3f32_mem4.z
166 + f32_mem5;
167
168 printf(" sum = %f\n", sum);
169
170 return sum;
171}
172
173
174//
175// PInvoke native call for Vector3 argument
176//
177
178EXPORT(Vector3) __stdcall nativeCall_PInvoke_Vector3Ret()
179{
180 Vector3 ret;
181 ret.x = 1;
182 ret.y = 2;
183 ret.z = 3;
184 float sum = ret.x + ret.y + ret.z;
185 printf("nativeCall_PInvoke_Vector3Ret:\n");
186 printf(" Return value: (%f, %f, %f)\n", ret.x, ret.y, ret.z);
187 printf(" Sum of return scalar values = %f\n", sum);
188 fflush(stdout);
189 return ret;
190}
191
192//
193// PInvoke native call for Vector3 array
194//
195
196EXPORT(float) __stdcall nativeCall_PInvoke_Vector3Array(Vector3* arr)
197{
198 float sum = 0.0;
199 printf("nativeCall_PInvoke_Vector3Array\n");
200 for (unsigned i = 0; i < 2; ++i)
201 {
202 Vector3* e = &arr[i];
203 printf(" arrEle[%d]: %f %f %f\n", i, e->x, e->y, e->z);
204 sum += e->x + e->y + e->z;
205 }
206 printf(" Sum = %f\n", sum);
207 fflush(stdout);
208 return sum;
209}
210
211//
212// PInvoke native call for Vector3 in struct
213//
214
215EXPORT(DT) __stdcall nativeCall_PInvoke_Vector3InStruct(DT data)
216{
217 printf("nativeCall_PInvoke_Vector3InStruct\n");
218 DT ret;
219 ret.a.x = data.a.x + 1;
220 ret.a.y = data.a.y + 1;
221 ret.a.z = data.a.z + 1;
222 ret.b.x = data.b.x + 1;
223 ret.b.y = data.b.y + 1;
224 ret.b.z = data.b.z + 1;
225 printf(" First struct memeber: (%f %f %f) -> (%f %f %f)\n",
226 data.a.x, data.a.y, data.a.z, ret.a.x, ret.a.y, ret.a.z);
227 printf(" Second struct member: (%f %f %f) -> (%f %f %f)\n",
228 data.b.x, data.b.y, data.b.z, ret.b.x, ret.b.y, ret.b.z);
229 float sum = ret.a.x + ret.a.y + ret.a.z + ret.b.x + ret.b.y + ret.b.z;
230 printf(" Sum of all return scalar values = %f\n", sum);
231 fflush(stdout);
232 return ret;
233}
234
235//
236// PInvoke native call for Vector3 in complex struct
237//
238
239EXPORT(void) __stdcall nativeCall_PInvoke_Vector3InComplexStruct(ComplexDT* arg)
240{
241 printf("nativeCall_PInvoke_Vector3InComplexStruct\n");
242 printf(" Arg ival: %d\n", arg->iv);
243 printf(" Arg Vector3 v1: (%f %f %f)\n", arg->vecs.a.x, arg->vecs.a.y, arg->vecs.a.z);
244 printf(" Arg Vector3 v2: (%f %f %f)\n", arg->vecs.b.x, arg->vecs.b.y, arg->vecs.b.z);
245 printf(" Arg Vector3 v3: (%f %f %f)\n", arg->v3.x, arg->v3.y, arg->v3.z);
246 printf(" Arg string arg: %s\n", arg->str);
247
248 arg->vecs.a.x = arg->vecs.a.x + 1;
249 arg->vecs.a.y = arg->vecs.a.y + 1;
250 arg->vecs.a.z = arg->vecs.a.z + 1;
251 arg->vecs.b.x = arg->vecs.b.x + 1;
252 arg->vecs.b.y = arg->vecs.b.y + 1;
253 arg->vecs.b.z = arg->vecs.b.z + 1;
254 arg->v3.x = arg->v3.x + 1;
255 arg->v3.y = arg->v3.y + 1;
256 arg->v3.z = arg->v3.z + 1;
257 arg->iv = arg->iv + 1;
258 snprintf(arg->str, _countof(arg->str), "%s", "ret_string");
259
260 printf(" Return ival: %d\n", arg->iv);
261 printf(" Return Vector3 v1: (%f %f %f)\n", arg->vecs.a.x, arg->vecs.a.y, arg->vecs.a.z);
262 printf(" Return Vector3 v2: (%f %f %f)\n", arg->vecs.b.x, arg->vecs.b.y, arg->vecs.b.z);
263 printf(" Return Vector3 v3: (%f %f %f)\n", arg->v3.x, arg->v3.y, arg->v3.z);
264 printf(" Return string arg: %s\n", arg->str);
265 float sum = arg->vecs.a.x + arg->vecs.a.y + arg->vecs.a.z
266 + arg->vecs.b.x + arg->vecs.b.y + arg->vecs.b.z
267 + arg->v3.x + arg->v3.y + arg->v3.z;
268 printf(" Sum of all return float scalar values = %f\n", sum);
269 fflush(stdout);
270}
271
272//
273// RPInvoke native call for Vector3 argument
274//
275typedef void (CALLBACK *CallBack_RPInvoke_Vector3Arg)(int i, Vector3 v1, char* s, Vector3 v2);
276
277
278EXPORT(void) __stdcall nativeCall_RPInvoke_Vector3Arg(
279 CallBack_RPInvoke_Vector3Arg notify)
280{
281 int i = 123;
282 const static char* str = "abcdefg";
283 Vector3 v1, v2;
284 v1.x = 1; v1.y = 2; v1.z = 3;
285 v2.x = 10; v2.y = 20; v2.z = 30;
286 notify(i, v1, (char*)str, v2);
287}
288
289
290
291//
292// RPInvoke native call for Vector3 argument
293//
294typedef void (CALLBACK *CallBack_RPInvoke_Vector3Arg_Unix)(
295 Vector3 v3f32_xmm0,
296 float f32_xmm2,
297 float f32_xmm3,
298 float f32_xmm4,
299 float f32_xmm5,
300 float f32_xmm6,
301 float f32_xmm7,
302 float f32_mem0,
303 Vector3 v3f32_mem1,
304 float f32_mem2,
305 float f32_mem3);
306
307
308EXPORT(void) __stdcall nativeCall_RPInvoke_Vector3Arg_Unix(
309 CallBack_RPInvoke_Vector3Arg_Unix notify)
310{
311 Vector3 v1, v2;
312 v1.x = 1; v1.y = 2; v1.z = 3;
313 v2.x = 10; v2.y = 20; v2.z = 30;
314 float f0 = 100, f1 = 101, f2 = 102, f3 = 103, f4 = 104, f5 = 105, f6 = 106, f7 = 107, f8 = 108;
315 notify(
316 v1,
317 f0, f1, f2, f3, f4, f5,
318 f6, // mapped onto stack
319 v2,
320 f7, f8);
321}
322
323
324
325//
326// RPInvoke native call for Vector3 argument
327//
328typedef void (CALLBACK *CallBack_RPInvoke_Vector3Arg_Unix2)(
329 Vector3 v3f32_xmm0,
330 float f32_xmm2,
331 float f32_xmm3,
332 float f32_xmm4,
333 float f32_xmm5,
334 float f32_xmm6,
335 float f32_xmm7,
336 float f32_mem0,
337 Vector3 v3f32_mem1,
338 float f32_mem2,
339 float f32_mem3,
340 Vector3 v3f32_mem4,
341 float f32_mem5);
342
343
344EXPORT(void) __stdcall nativeCall_RPInvoke_Vector3Arg_Unix2(
345 CallBack_RPInvoke_Vector3Arg_Unix2 notify)
346{
347 Vector3 v1, v2, v3;
348 v1.x = 1; v1.y = 2; v1.z = 3;
349 v2.x = 4; v2.y = 5; v2.z = 6;
350 v3.x = 7; v3.y = 8; v3.z = 9;
351 float f0 = 100, f1 = 101, f2 = 102, f3 = 103, f4 = 104, f5 = 105, f6 = 106, f7 = 107, f8 = 108, f9 = 109;
352 notify(
353 v1,
354 f0, f1, f2, f3, f4, f5,
355 f6, // mapped onto stack
356 v2,
357 f7, f8,
358 v3,
359 f9);
360}
361
362
363//
364// RPInvoke native call for Vector3 array
365//
366
367typedef Vector3 (CALLBACK *CallBack_RPInvoke_Vector3Ret)();
368
369EXPORT(bool) __stdcall nativeCall_RPInvoke_Vector3Ret(
370 CallBack_RPInvoke_Vector3Ret notify)
371{
372 Vector3 ret = notify();
373 printf("nativeCall_RPInvoke_Vector3Ret:\n Return value (%f %f %f)\n",
374 ret.x, ret.y, ret.z);
375 fflush(stdout);
376 if (ret.x == 1 && ret.y == 2 && ret.z == 3) {
377 return true;
378 }
379 return false;
380}
381
382//
383// RPInvoke native call for Vector3 array
384//
385
386typedef void (CALLBACK *CallBack_RPInvoke_Vector3Array)(Vector3* v, int size);
387
388static Vector3 arr[2];
389
390EXPORT(void) __stdcall nativeCall_RPInvoke_Vector3Array(
391 CallBack_RPInvoke_Vector3Array notify,
392 int a)
393{
394 arr[0].x = a + 1.0f;
395 arr[0].y = a + 2.0f;
396 arr[0].z = a + 3.0f;
397 arr[1].x = a + 10.0f;
398 arr[1].y = a + 20.0f;
399 arr[1].z = a + 30.0f;
400 notify(arr, 2);
401}
402
403//
404// RPInvoke native call for Vector3-in-struct test
405//
406
407typedef void (CALLBACK *CallBack_RPInvoke_Vector3InStruct)(DT v);
408
409static DT v;
410
411EXPORT(void) __stdcall nativeCall_RPInvoke_Vector3InStruct(
412 CallBack_RPInvoke_Vector3InStruct notify,
413 int a)
414{
415 v.a.x = a + 1.0f;
416 v.a.y = a + 2.0f;
417 v.a.z = a + 3.0f;
418 v.b.x = a + 10.0f;
419 v.b.y = a + 20.0f;
420 v.b.z = a + 30.0f;
421 notify(v);
422}
423
424//
425// RPInvoke native call for complex Vector3-in-struct test
426//
427
428typedef bool (CALLBACK *CallBack_RPInvoke_Vector3InComplexStruct)(ComplexDT* v);
429
430EXPORT(bool) __stdcall nativeCall_RPInvoke_Vector3InComplexStruct(
431 CallBack_RPInvoke_Vector3InComplexStruct notify)
432{
433 static ComplexDT cdt;
434 cdt.iv = 99;
435 snprintf(cdt.str, _countof("arg_string"), "%s", "arg_string");
436 cdt.vecs.a.x = 1; cdt.vecs.a.y = 2; cdt.vecs.a.z = 3;
437 cdt.vecs.b.x = 5; cdt.vecs.b.y = 6; cdt.vecs.b.z = 7;
438 cdt.v3.x = 10; cdt.v3.y = 20; cdt.v3.z = 30;
439
440 notify(&cdt);
441
442 printf(" Native ival: %d\n", cdt.iv);
443 printf(" Native Vector3 v1: (%f %f %f)\n", cdt.vecs.a.x, cdt.vecs.a.y, cdt.vecs.a.z);
444 printf(" Native Vector3 v2: (%f %f %f)\n", cdt.vecs.b.x, cdt.vecs.b.y, cdt.vecs.b.z);
445 printf(" Native Vector3 v3: (%f %f %f)\n", cdt.v3.x, cdt.v3.y, cdt.v3.z);
446 printf(" Native string arg: %s\n", cdt.str);
447 fflush(stdout);
448
449 // Expected return value = 2 + 3 + 4 + 6 + 7 + 8 + 11 + 12 + 13 = 93
450 float sum = cdt.vecs.a.x + cdt.vecs.a.y + cdt.vecs.a.z
451 + cdt.vecs.b.x + cdt.vecs.b.y + cdt.vecs.b.z
452 + cdt.v3.x + cdt.v3.y + cdt.v3.z;
453
454 if ((sum != 93) || (cdt.iv != 100) || (strcmp(cdt.str, "ret_string")!=0) )
455 {
456 return false;
457 }
458 return true;
459}
460