2 Copyright (C) 2001-2007, Parrot Foundation.
7 src/nci_test.c - shared library used for testing the Native Call Interface
11 From this code a shared library can be compiled and linked with a command like:
13 cc -shared -fpic nci_test.c -o libnci_test.so -g
15 For non-Unix platforms the above command has to be modified appropriately.
17 The resulting shared library should be copied to a location like:
19 parrot/runtime/parrot/dynext/libnci_test.so
21 At that location the shared library is loadable with the opcode 'loadlib'.
22 The functions in the library are available with the opcode 'dlfunc'.
23 The variables in the library are available with the opcode 'dlvar'.
27 The name of a test function is usually 'nci_<signature>'. E.g. the function
28 'nci_ip' takes a 'pointer' and returns a 'int'.
36 #define PARROT_IN_EXTENSION
40 #include <parrot/parrot.h>
47 /* Declarations of structs */
49 typedef struct Nested
{
53 typedef struct Outer
{
58 typedef struct Rect_Like
{
63 typedef struct Opaque
{
67 /* Function declarations.
69 *** If you add a new test function here,
70 *** please update src/libnci_test.def and src/call_list.txt too. ***
74 PARROT_DYNEXT_EXPORT
int call_back(const char *str
);
75 PARROT_DYNEXT_EXPORT
char nci_c(void);
76 PARROT_DYNEXT_EXPORT
char nci_csc(short, char);
77 PARROT_DYNEXT_EXPORT
double nci_d(void);
78 PARROT_DYNEXT_EXPORT
double nci_dd(double);
79 PARROT_DYNEXT_EXPORT
float nci_f(void);
80 PARROT_DYNEXT_EXPORT
float nci_fff(float, float);
81 PARROT_DYNEXT_EXPORT
int nci_i(void);
82 PARROT_DYNEXT_EXPORT
int nci_ib(int *);
83 PARROT_DYNEXT_EXPORT
int nci_iiii(int, int, int);
84 PARROT_DYNEXT_EXPORT
int nci_ii3(int, int *);
85 PARROT_DYNEXT_EXPORT
int nci_ip(void *);
86 PARROT_DYNEXT_EXPORT
int nci_isc(short, char);
87 PARROT_DYNEXT_EXPORT
int nci_it(void *);
88 PARROT_DYNEXT_EXPORT
int nci_i33(int *, int *);
89 PARROT_DYNEXT_EXPORT
int nci_i4i(long *, int);
90 PARROT_DYNEXT_EXPORT
long nci_l(void);
91 PARROT_DYNEXT_EXPORT
int * nci_p(void);
92 PARROT_DYNEXT_EXPORT
void * nci_pi(int);
93 PARROT_DYNEXT_EXPORT
void * nci_pii(int, int);
94 PARROT_DYNEXT_EXPORT
void * nci_piiii(int, int, int, int);
95 PARROT_DYNEXT_EXPORT
void nci_pip(int, Rect_Like
*);
96 PARROT_DYNEXT_EXPORT
void * nci_pp(void *);
97 PARROT_DYNEXT_EXPORT
short nci_s(void);
98 PARROT_DYNEXT_EXPORT
short nci_ssc(short, char);
99 PARROT_DYNEXT_EXPORT
char * nci_t(void);
100 PARROT_DYNEXT_EXPORT
char * nci_tb(void *);
101 PARROT_DYNEXT_EXPORT
char * nci_tB(void **);
102 PARROT_DYNEXT_EXPORT
char * nci_tt(void *);
103 PARROT_DYNEXT_EXPORT
void nci_v(void);
104 PARROT_DYNEXT_EXPORT
void nci_vP(void *);
105 PARROT_DYNEXT_EXPORT
void nci_vpii(Outer
*, int, int);
106 PARROT_DYNEXT_EXPORT
void nci_vv(void);
107 PARROT_DYNEXT_EXPORT
void nci_vVi(Opaque
**, int);
108 PARROT_DYNEXT_EXPORT
void nci_vp(Opaque
*);
109 PARROT_DYNEXT_EXPORT
char * nci_ttt(char *, char *);
110 PARROT_DYNEXT_EXPORT
void nci_vfff(float, float, float);
111 PARROT_DYNEXT_EXPORT
void nci_vV(const char **);
112 PARROT_DYNEXT_EXPORT
void nci_vVVV(const char **, const char **, const char **);
114 /* Declarations for callback tests */
116 typedef void (*cb_C1_func
)(const char*, void*);
117 PARROT_DYNEXT_EXPORT
void nci_cb_C1(cb_C1_func
, void*);
119 typedef void (*cb_C2_func
)(int, void*);
120 PARROT_DYNEXT_EXPORT
void nci_cb_C2(cb_C2_func
, void*);
122 typedef void (*cb_C3_func
)(void*, void*);
123 PARROT_DYNEXT_EXPORT
void nci_cb_C3(cb_C3_func
, void*);
125 typedef void (*cb_D1_func
)(void*, const char*);
126 PARROT_DYNEXT_EXPORT
void nci_cb_D1(cb_D1_func
, void*);
128 typedef void (*cb_D2_func
)(void*, int);
129 PARROT_DYNEXT_EXPORT
void nci_cb_D2(cb_D2_func
, void*);
131 typedef void (*cb_D3_func
)(void*, void*);
132 PARROT_DYNEXT_EXPORT
void nci_cb_D3(cb_D3_func
, void*);
134 typedef void (*cb_D4_func
)(void*, void*);
135 PARROT_DYNEXT_EXPORT
void nci_cb_D4(cb_D4_func
, void*);
137 /* Variable definitions */
139 PARROT_DYNEXT_EXPORT
int int_cb_D4
= -55555;
140 PARROT_DYNEXT_EXPORT
int nci_dlvar_char
= 22;
141 PARROT_DYNEXT_EXPORT
int nci_dlvar_short
= 333;
142 PARROT_DYNEXT_EXPORT
int nci_dlvar_int
= -4444;
143 PARROT_DYNEXT_EXPORT
long nci_dlvar_long
= -7777777;
144 PARROT_DYNEXT_EXPORT
float nci_dlvar_float
= -333.0;
145 PARROT_DYNEXT_EXPORT
double nci_dlvar_double
= -55555.55555;
146 PARROT_DYNEXT_EXPORT
char nci_dlvar_cstring
[] = "This is a C-string.\n";
149 /* Function definitions */
153 =item C<PARROT_DYNEXT_EXPORT char
156 Returns the value of the variable C<nci_dlvar_char>, which is set to 22 by
163 PARROT_DYNEXT_EXPORT
char
165 return nci_dlvar_char
;
170 =item C<PARROT_DYNEXT_EXPORT char
171 nci_csc(short l1, char l2)>
173 Multiplies C<l1> and C<l2> together and returns the first byte of the result.
179 PARROT_DYNEXT_EXPORT
char
180 nci_csc(short l1
, char l2
)
187 =item C<PARROT_DYNEXT_EXPORT double
190 Multiplies the current value of C<nci_dlvar_double> by 10.0, and returns
197 PARROT_DYNEXT_EXPORT
double
200 nci_dlvar_double
*= 10.0;
202 return nci_dlvar_double
;
207 =item C<PARROT_DYNEXT_EXPORT double
210 Returns the value C<d> multiplied by 2.0.
216 PARROT_DYNEXT_EXPORT
double
224 =item C<PARROT_DYNEXT_EXPORT float
227 Multiplies the value C<nci_dlvar_float> by 10.0 and returns the new
234 PARROT_DYNEXT_EXPORT
float
237 nci_dlvar_float
*= 10.0;
239 return nci_dlvar_float
;
244 =item C<PARROT_DYNEXT_EXPORT float
245 nci_fff(float l1, float l2)>
247 Returns the result of C<l1> / C<l2>.
253 PARROT_DYNEXT_EXPORT
float
254 nci_fff(float l1
, float l2
)
261 =item C<PARROT_DYNEXT_EXPORT int
264 Returns the current value of <nci_dlvar_int>.
270 PARROT_DYNEXT_EXPORT
int
273 return nci_dlvar_int
;
278 =item C<PARROT_DYNEXT_EXPORT int
279 nci_isc(short l1, char l2)>
281 Returns the int product of C<l1 * l2>.
287 PARROT_DYNEXT_EXPORT
int
288 nci_isc(short l1
, char l2
)
295 =item C<PARROT_DYNEXT_EXPORT int
298 Performs a series of operations on values stored at pointer C<p>.
304 PARROT_DYNEXT_EXPORT
int
307 typedef struct _dfi
{
317 return (int) (sp
->d
+ sp
->f
+ sp
->i
);
322 =item C<PARROT_DYNEXT_EXPORT int
325 test calls this with a string
331 PARROT_DYNEXT_EXPORT
int
334 fprintf(stderr
, "%c%c\n", ((char*) p
)[1], ((char *) p
)[0]);
342 =item C<PARROT_DYNEXT_EXPORT long
345 Returns the value of C<nci_dlvar_long>.
351 PARROT_DYNEXT_EXPORT
long
354 return nci_dlvar_long
;
359 =item C<PARROT_DYNEXT_EXPORT int *
362 Returns the address of C<nci_dlvar_int>.
368 PARROT_DYNEXT_EXPORT
int *
371 return &nci_dlvar_int
;
376 =item C<PARROT_DYNEXT_EXPORT char *
379 Returns the value of C<nci_dlvar_cstring>.
385 PARROT_DYNEXT_EXPORT
char *
388 return nci_dlvar_cstring
;
393 =item C<PARROT_DYNEXT_EXPORT char *
396 Prints "xx worked", where "xx" is replaced with the first two character values
397 of C<p>, in reverse order.
403 static char b
[] = "xx worked\n";
405 PARROT_DYNEXT_EXPORT
char *
408 b
[0] = ((char*) p
)[1];
409 b
[1] = ((char*) p
)[0];
416 =item C<PARROT_DYNEXT_EXPORT char *
419 Prints "xx worked", where "xx" is replaced with the first two character values
420 of C<p>, in reverse order.
426 static char s
[] = "xx worked\n";
428 PARROT_DYNEXT_EXPORT
char *
431 s
[0] = ((char*) p
)[1];
432 s
[1] = ((char*) p
)[0];
439 =item C<PARROT_DYNEXT_EXPORT char *
442 Prints "xx done", where "xx" is replaced with the first two character values
443 of C<p>, in reverse order.
449 static char B
[] = "xx done\n";
451 PARROT_DYNEXT_EXPORT
char *
454 B
[0] = (*(char**) p
)[1];
455 B
[1] = (*(char**) p
)[0];
462 =item C<PARROT_DYNEXT_EXPORT void *
465 Returns the value C<p> directly.
471 PARROT_DYNEXT_EXPORT
void *
479 =item C<PARROT_DYNEXT_EXPORT int
480 nci_iiii(int i1, int i2, int i3)>
482 Prints three integers separated by whitespace to C<stderr>.
488 PARROT_DYNEXT_EXPORT
int
489 nci_iiii(int i1
, int i2
, int i3
)
491 fprintf(stderr
, "%d %d %d\n", i1
, i2
, i3
);
499 =item C<PARROT_DYNEXT_EXPORT int
500 nci_i4i(long * l, int i)>
502 Returns the product of C<*l> and C<i>, as an int.
508 PARROT_DYNEXT_EXPORT
int
509 nci_i4i(long * l
, int i
)
512 return (int) (*l
* i
);
517 =item C<PARROT_DYNEXT_EXPORT int
518 nci_ii3(int a, int *bp)>
520 Multiplies C<a> and C<*bp> together and returns the result. Updates C<*bp>
527 PARROT_DYNEXT_EXPORT
int
528 nci_ii3(int a
, int *bp
)
538 =item C<PARROT_DYNEXT_EXPORT int
539 call_back(const char *str)>
541 writes the string C<str> to stdout and returns the value 4711.
547 PARROT_DYNEXT_EXPORT
int
548 call_back(const char *str
)
558 =item C<PARROT_DYNEXT_EXPORT void *
561 Performs one from a series of tests, depending on the value given for C<test>.
567 PARROT_DYNEXT_EXPORT
void *
621 } xx
= { 100, 77, 200.0 };
634 int (*f
)(const char *);
693 static int i
= 55555;
699 fprintf(stderr
, "unknown test number\n");
707 =item C<PARROT_DYNEXT_EXPORT short
710 Returns the value of C<nci_dlvar_short>.
716 PARROT_DYNEXT_EXPORT
short
719 return nci_dlvar_short
;
724 =item C<PARROT_DYNEXT_EXPORT short
725 nci_ssc(short l1, char l2)>
727 Returns the product of C<l1 * l2>.
733 PARROT_DYNEXT_EXPORT
short
734 nci_ssc(short l1
, char l2
)
741 =item C<PARROT_DYNEXT_EXPORT void
744 Prints "ok" if C<PMC> is not null, prints "got null" otherwise.
750 PARROT_DYNEXT_EXPORT
void
753 /* Disable this test until someone figures a way to check for
754 * PMCNULL without using libparrot.
755 if (!PMC_IS_NULL(pmc))
767 =head2 Functions used for pdd16 tests
777 =item C<PARROT_DYNEXT_EXPORT void
778 nci_cb_C1(cb_C1_func cb, void* user_data)>
780 Calls C<cb> function with the string "result" and the given C<user_data>.
787 PARROT_DYNEXT_EXPORT
void
788 nci_cb_C1(cb_C1_func cb
, void* user_data
)
790 const char *result
= "succeeded";
791 /* call the cb synchronously */
792 (cb
)(result
, user_data
);
799 =item C<PARROT_DYNEXT_EXPORT void
800 nci_cb_C2(cb_C2_func cb, void* user_data)>
802 Calls the function C<cb> with the pointer C<user_data>. No return value.
808 PARROT_DYNEXT_EXPORT
void
809 nci_cb_C2(cb_C2_func cb
, void* user_data
)
811 /* call the cb synchronously */
819 =item C<PARROT_DYNEXT_EXPORT void
820 nci_cb_C3(cb_C3_func cb, void* user_data)>
822 Calls function C<cb> with data C<user_data>. No return value.
828 static int int_cb_C3
= 99;
830 PARROT_DYNEXT_EXPORT
void
831 nci_cb_C3(cb_C3_func cb
, void* user_data
)
833 /* call the cb synchronously */
834 (cb
)(&int_cb_C3
, user_data
);
841 =item C<PARROT_DYNEXT_EXPORT void
842 nci_cb_D1(cb_D1_func cb, void* user_data)>
844 Calls function C<cb> with data C<user_data>. No return value.
850 PARROT_DYNEXT_EXPORT
void
851 nci_cb_D1(cb_D1_func cb
, void* user_data
)
853 const char *result
= "succeeded";
854 /* call the cb synchronously */
855 (cb
)(user_data
, result
);
862 =item C<PARROT_DYNEXT_EXPORT void
863 nci_cb_D2(cb_D2_func cb, void* user_data)>
865 Calls function C<cb> with data C<user_data>.
871 PARROT_DYNEXT_EXPORT
void
872 nci_cb_D2(cb_D2_func cb
, void* user_data
)
874 /* call the cb synchronously */
882 =item C<PARROT_DYNEXT_EXPORT void
883 nci_cb_D3(cb_D3_func cb, void* user_data)>
885 Calls function C<cb> with data C<user_data>.
891 static int int_cb_D3
= 111;
893 PARROT_DYNEXT_EXPORT
void
894 nci_cb_D3(cb_D3_func cb
, void* user_data
)
896 /* call the cb synchronously */
897 (cb
)(user_data
, &int_cb_D3
);
904 =item C<PARROT_DYNEXT_EXPORT void
905 nci_cb_D4(cb_D4_func times_ten, void* user_data)>
907 Calls function C<times_ten> with data C<user_data> 10 times in a loop.
913 PARROT_DYNEXT_EXPORT
void
914 nci_cb_D4(cb_D4_func times_ten
, void* user_data
)
917 for (cnt
= 0; cnt
< 9; cnt
++)
919 (times_ten
)(user_data
, &int_cb_D4
);
928 =item C<PARROT_DYNEXT_EXPORT void
929 nci_pip(int count, Rect_Like *rects)>
931 Prints a count integer and the coordinates of 4 rectangles.
937 PARROT_DYNEXT_EXPORT
void
938 nci_pip(int count
, Rect_Like
*rects
)
941 printf("Count: %d\n", count
);
942 for (i
= 0; i
< 4; ++i
)
943 printf("X: %d\nY: %d\nW: %d\nH: %d\n",
944 rects
[i
].x
, rects
[i
].y
, rects
[i
].w
, rects
[i
].h
);
949 =item C<PARROT_DYNEXT_EXPORT int
950 nci_i33(int *double_me, int *triple_me)>
952 Returns the result C<*double_me * 2 + *triple_me * 3>.
958 PARROT_DYNEXT_EXPORT
int
959 nci_i33(int *double_me
, int *triple_me
)
964 return (*double_me
+ *triple_me
);
969 =item C<PARROT_DYNEXT_EXPORT void
970 nci_vpii(Outer *my_data, int my_x, int my_y)>
972 Updates data in structure pointer C<my_data> with the given data C<my_x> and
979 PARROT_DYNEXT_EXPORT
void
980 nci_vpii(Outer
*my_data
, int my_x
, int my_y
)
983 my_data
->nested
->y
= my_y
;
988 =item C<PARROT_DYNEXT_EXPORT void *
989 nci_piiii(int alpha, int beta, int gamma, int delta)>
991 Stores 4 integer values into an array structure, and returns the address
998 static int my_array
[4];
1000 PARROT_DYNEXT_EXPORT
void *
1001 nci_piiii(int alpha
, int beta
, int gamma
, int delta
)
1003 static struct array_container
1009 my_array
[0] = alpha
;
1011 my_array
[2] = gamma
;
1012 my_array
[3] = delta
;
1015 container
.array
= my_array
;
1022 =item C<PARROT_DYNEXT_EXPORT void *
1023 nci_pii(int fac1, int fac2)>
1025 Returns the address of global variable C<nci_dlvar_int> whose value is set
1026 to the product of C<fac1 * fac2>.
1032 PARROT_DYNEXT_EXPORT
void *
1033 nci_pii(int fac1
, int fac2
)
1035 nci_dlvar_int
= fac1
* fac2
;
1037 return &nci_dlvar_int
;
1042 =item C<PARROT_DYNEXT_EXPORT void
1045 Multiplies the global variable C<nci_dlvar_int> times 10.
1051 PARROT_DYNEXT_EXPORT
void
1054 nci_dlvar_int
*= 10;
1059 =item C<PARROT_DYNEXT_EXPORT void
1062 Multiplies the global variable C<nci_dlvar_int> by 3.
1068 PARROT_DYNEXT_EXPORT
void
1076 =item C<PARROT_DYNEXT_EXPORT void
1077 nci_vVi(Opaque**, int)>
1079 Test an NCI opaque struct out value.
1085 PARROT_DYNEXT_EXPORT
void
1086 nci_vVi(Opaque
**outOpaque
, int x
)
1088 static Opaque opaque
;
1090 *outOpaque
= &opaque
;
1095 =item C<PARROT_DYNEXT_EXPORT int
1098 Test that a previously generated opaque struct gets passed back
1099 to an NCI function correctly.
1105 PARROT_DYNEXT_EXPORT
void
1106 nci_vp(Opaque
*inOpaque
)
1109 printf("got %d\n", inOpaque
->x
);
1111 printf("got null\n");
1116 =item C<PARROT_DYNEXT_EXPORT char *
1119 Prints "s2, s1, s1d"
1125 PARROT_DYNEXT_EXPORT
char *
1126 nci_ttt(char *s1
, char *s2
)
1128 char* s
= (char*) malloc(strlen(s2
) + (2 * strlen(s1
)) + 5);
1129 sprintf(s
, "%s, %s, %s", s2
, s2
, s1
);
1135 static void validate_float(float f
, double checkval
) {
1138 error_ratio
= (((double)f
) - checkval
) / checkval
;
1139 valid
= error_ratio
<= 0.01 && error_ratio
>= -0.01;
1140 printf("%i\n", valid
);
1145 =item C<PARROT_DYNEXT_EXPORT float
1146 nci_fff(float l1, float l2)>
1148 Returns the result of C<l1> / C<l2>.
1154 PARROT_DYNEXT_EXPORT
void
1155 nci_vfff(float l1
, float l2
, float l3
)
1157 validate_float(l1
, 3456.54);
1158 validate_float(l2
, 10.1999);
1159 validate_float(l3
, 14245.567);
1165 =item C<PARROT_DYNEXT_EXPORT float
1166 nci_fff(float l1, float l2)>
1168 Returns the result of C<l1> / C<l2>.
1174 PARROT_DYNEXT_EXPORT
void
1175 nci_vV(const char **ptr
)
1177 *ptr
= "Hello bright new world\n";
1182 =item C<PARROT_DYNEXT_EXPORT float
1183 nci_fff(float l1, float l2)>
1185 Returns the result of C<l1> / C<l2>.
1191 PARROT_DYNEXT_EXPORT
void
1192 nci_vVVV(const char **ptr1
, const char **ptr2
, const char **ptr3
)
1194 *ptr1
= "Hello bright new world!\n";
1195 *ptr2
= "It is a beautiful day!\n";
1196 *ptr3
= "Go suck a lemon.\n";
1209 Calls test functions C<nci_ssc> and C<nci_fff> and prints their results.
1220 int l
= nci_ssc(l1
, l2
);
1222 f
= nci_fff(f1
, f2
);
1240 F<docs/pdds/pdd16_native_call.pod>
1241 F<config/gen/makefiles/root.in>
1251 * c-file-style: "parrot"
1253 * vim: expandtab shiftwidth=4: