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/nci/extra_thunks.nci 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(char *);
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 nci_c(void)>
155 Returns the value of the variable C<nci_dlvar_char>, which is set to 22 by
162 PARROT_DYNEXT_EXPORT
char
164 return nci_dlvar_char
;
169 =item C<PARROT_DYNEXT_EXPORT char nci_csc(short l1, char l2)>
171 Multiplies C<l1> and C<l2> together and returns the first byte of the result.
177 PARROT_DYNEXT_EXPORT
char
178 nci_csc(short l1
, char l2
)
185 =item C<PARROT_DYNEXT_EXPORT double nci_d(void)>
187 Multiplies the current value of C<nci_dlvar_double> by 10.0, and returns
194 PARROT_DYNEXT_EXPORT
double
197 nci_dlvar_double
*= 10.0;
199 return nci_dlvar_double
;
204 =item C<PARROT_DYNEXT_EXPORT double nci_dd(double d)>
206 Returns the value C<d> multiplied by 2.0.
212 PARROT_DYNEXT_EXPORT
double
220 =item C<PARROT_DYNEXT_EXPORT float nci_f(void)>
222 Multiplies the value C<nci_dlvar_float> by 10.0 and returns the new
229 PARROT_DYNEXT_EXPORT
float
232 nci_dlvar_float
*= 10.0;
234 return nci_dlvar_float
;
239 =item C<PARROT_DYNEXT_EXPORT float nci_fff(float l1, float l2)>
241 Returns the result of C<l1> / C<l2>.
247 PARROT_DYNEXT_EXPORT
float
248 nci_fff(float l1
, float l2
)
255 =item C<PARROT_DYNEXT_EXPORT int nci_i(void)>
257 Returns the current value of <nci_dlvar_int>.
263 PARROT_DYNEXT_EXPORT
int
266 return nci_dlvar_int
;
271 =item C<PARROT_DYNEXT_EXPORT int nci_isc(short l1, char l2)>
273 Returns the int product of C<l1 * l2>.
279 PARROT_DYNEXT_EXPORT
int
280 nci_isc(short l1
, char l2
)
287 =item C<PARROT_DYNEXT_EXPORT int nci_ip(void *p)>
289 Performs a series of operations on values stored at pointer C<p>.
295 PARROT_DYNEXT_EXPORT
int
298 typedef struct _dfi
{
308 return (int) (sp
->d
+ sp
->f
+ sp
->i
);
313 =item C<PARROT_DYNEXT_EXPORT int nci_it(void *p)>
315 Prints the first two characters in C<p>, in reversed order. Returns 2.
321 PARROT_DYNEXT_EXPORT
int
324 fprintf(stderr
, "%c%c\n", ((char*) p
)[1], ((char *) p
)[0]);
332 =item C<PARROT_DYNEXT_EXPORT long nci_l(void)>
334 Returns the value of C<nci_dlvar_long>.
340 PARROT_DYNEXT_EXPORT
long
343 return nci_dlvar_long
;
348 =item C<PARROT_DYNEXT_EXPORT int * nci_p(void)>
350 Returns the address of C<nci_dlvar_int>.
356 PARROT_DYNEXT_EXPORT
int *
359 return &nci_dlvar_int
;
364 =item C<PARROT_DYNEXT_EXPORT char * nci_t(void)>
366 Returns the value of C<nci_dlvar_cstring>.
372 PARROT_DYNEXT_EXPORT
char *
375 return nci_dlvar_cstring
;
380 =item C<PARROT_DYNEXT_EXPORT char * nci_tb(void *p)>
382 Returns "xx worked", where "xx" is replaced with the first two character values
383 of C<p>, in reverse order.
389 static char b
[] = "xx worked\n";
391 PARROT_DYNEXT_EXPORT
char *
394 b
[0] = ((char*) p
)[1];
395 b
[1] = ((char*) p
)[0];
402 =item C<PARROT_DYNEXT_EXPORT char * nci_tt(char *p)>
404 Returns "xx worked", where "xx" is replaced with the first two character values
405 of C<p>, in reverse order.
411 static char s
[] = "xx worked\n";
413 PARROT_DYNEXT_EXPORT
char *
424 =item C<PARROT_DYNEXT_EXPORT char * nci_tB(void **p)>
426 Returns "xx done", where "xx" is replaced with the first two character values
427 of C<p>, in reverse order.
433 static char B
[] = "xx done\n";
435 PARROT_DYNEXT_EXPORT
char *
438 B
[0] = (*(char**) p
)[1];
439 B
[1] = (*(char**) p
)[0];
446 =item C<PARROT_DYNEXT_EXPORT void * nci_pp(void *p)>
448 Returns the value C<p> directly.
454 PARROT_DYNEXT_EXPORT
void *
462 =item C<PARROT_DYNEXT_EXPORT int nci_iiii(int i1, int i2, int i3)>
464 Prints three integers separated by whitespace to C<stderr>.
471 PARROT_DYNEXT_EXPORT
int
472 nci_iiii(int i1
, int i2
, int i3
)
474 fprintf(stderr
, "%d %d %d\n", i1
, i2
, i3
);
482 =item C<PARROT_DYNEXT_EXPORT int nci_i4i(long * l, int i)>
484 Returns the product of C<*l> and C<i>, as an int.
490 PARROT_DYNEXT_EXPORT
int
491 nci_i4i(long * l
, int i
)
494 return (int) (*l
* i
);
499 =item C<PARROT_DYNEXT_EXPORT int nci_ii3(int a, int *bp)>
501 Multiplies C<a> and C<*bp> together and returns the result. Updates C<*bp>
508 PARROT_DYNEXT_EXPORT
int
509 nci_ii3(int a
, int *bp
)
519 =item C<PARROT_DYNEXT_EXPORT int call_back(const char *str)>
521 writes the string C<str> to stdout and returns the value 4711.
527 PARROT_DYNEXT_EXPORT
int
528 call_back(const char *str
)
538 =item C<PARROT_DYNEXT_EXPORT void * nci_pi(int test)>
540 Performs one from a series of tests, depending on the value given for C<test>.
546 PARROT_DYNEXT_EXPORT
void *
600 } xx
= { 100, 77, 200.0 };
613 int (*f
)(const char *);
672 static int i
= 55555;
678 fprintf(stderr
, "unknown test number\n");
686 =item C<PARROT_DYNEXT_EXPORT short nci_s(void)>
688 Returns the value of C<nci_dlvar_short>.
694 PARROT_DYNEXT_EXPORT
short
697 return nci_dlvar_short
;
702 =item C<PARROT_DYNEXT_EXPORT short nci_ssc(short l1, char l2)>
704 Returns the product of C<l1 * l2>.
710 PARROT_DYNEXT_EXPORT
short
711 nci_ssc(short l1
, char l2
)
718 =item C<PARROT_DYNEXT_EXPORT void nci_vP(void *pmc)>
720 Prints "ok" if C<PMC> is not null, prints "got null" otherwise.
726 PARROT_DYNEXT_EXPORT
void
730 * Disable this test until someone figures a way to check for
731 * PMCNULL without using libparrot.
732 if (!PMC_IS_NULL(pmc))
744 =head2 Functions used for pdd16 tests
754 =item C<PARROT_DYNEXT_EXPORT void nci_cb_C1(cb_C1_func cb, void* user_data)>
756 Calls C<cb> function with the string "result" and the given C<user_data>.
763 PARROT_DYNEXT_EXPORT
void
764 nci_cb_C1(cb_C1_func cb
, void* user_data
)
766 const char *result
= "succeeded";
767 /* call the cb synchronously */
768 (cb
)(result
, user_data
);
775 =item C<PARROT_DYNEXT_EXPORT void nci_cb_C2(cb_C2_func cb, void* user_data)>
777 Calls the function C<cb> with the integer 77 and the given C<user_data>.
784 PARROT_DYNEXT_EXPORT
void
785 nci_cb_C2(cb_C2_func cb
, void* user_data
)
787 /* call the cb synchronously */
795 =item C<PARROT_DYNEXT_EXPORT void nci_cb_C3(cb_C3_func cb, void* user_data)>
797 Calls function C<cb> with C<&int_cb_C3> and the givn C<user_data>.
804 static int int_cb_C3
= 99;
806 PARROT_DYNEXT_EXPORT
void
807 nci_cb_C3(cb_C3_func cb
, void* user_data
)
809 /* call the cb synchronously */
810 (cb
)(&int_cb_C3
, user_data
);
817 =item C<PARROT_DYNEXT_EXPORT void nci_cb_D1(cb_D1_func cb, void* user_data)>
819 Calls function C<cb> with data C<user_data> and the string "succeeded".
826 PARROT_DYNEXT_EXPORT
void
827 nci_cb_D1(cb_D1_func cb
, void* user_data
)
829 const char *result
= "succeeded";
830 /* call the cb synchronously */
831 (cb
)(user_data
, result
);
838 =item C<PARROT_DYNEXT_EXPORT void nci_cb_D2(cb_D2_func cb, void* user_data)>
840 Calls function C<cb> with data C<user_data> and the integer 88.
847 PARROT_DYNEXT_EXPORT
void
848 nci_cb_D2(cb_D2_func cb
, void* user_data
)
850 /* call the cb synchronously */
858 =item C<PARROT_DYNEXT_EXPORT void nci_cb_D3(cb_D3_func cb, void* user_data)>
860 Calls function C<cb> with data C<user_data> and C<&int_cb_D3>.
867 static int int_cb_D3
= 111;
869 PARROT_DYNEXT_EXPORT
void
870 nci_cb_D3(cb_D3_func cb
, void* user_data
)
872 /* call the cb synchronously */
873 (cb
)(user_data
, &int_cb_D3
);
880 =item C<PARROT_DYNEXT_EXPORT void nci_cb_D4(cb_D4_func times_ten, void*
883 Calls function C<times_ten> with data C<user_data> and C<&int_cb_D4> 10 times
884 in a loop, incrementing C<int_cb_D4> after every call.
891 PARROT_DYNEXT_EXPORT
void
892 nci_cb_D4(cb_D4_func times_ten
, void* user_data
)
895 for (cnt
= 0; cnt
< 9; cnt
++)
897 (times_ten
)(user_data
, &int_cb_D4
);
906 =item C<PARROT_DYNEXT_EXPORT void nci_pip(int count, Rect_Like *rects)>
908 Prints a count integer and the coordinates of 4 rectangles.
914 PARROT_DYNEXT_EXPORT
void
915 nci_pip(int count
, Rect_Like
*rects
)
918 printf("Count: %d\n", count
);
919 for (i
= 0; i
< 4; ++i
)
920 printf("X: %d\nY: %d\nW: %d\nH: %d\n",
921 rects
[i
].x
, rects
[i
].y
, rects
[i
].w
, rects
[i
].h
);
926 =item C<PARROT_DYNEXT_EXPORT int nci_i33(int *double_me, int *triple_me)>
928 Doubles C<double_me> and triples C<triple_me>. Returns their sum.
934 PARROT_DYNEXT_EXPORT
int
935 nci_i33(int *double_me
, int *triple_me
)
940 return (*double_me
+ *triple_me
);
945 =item C<PARROT_DYNEXT_EXPORT void nci_vpii(Outer *my_data, int my_x, int my_y)>
947 Updates data in structure pointer C<my_data> with the given data C<my_x> and
954 PARROT_DYNEXT_EXPORT
void
955 nci_vpii(Outer
*my_data
, int my_x
, int my_y
)
958 my_data
->nested
->y
= my_y
;
963 =item C<PARROT_DYNEXT_EXPORT void * nci_piiii(int alpha, int beta, int gamma,
966 Stores 4 integer values into an array structure, and returns the address
973 static int my_array
[4];
975 PARROT_DYNEXT_EXPORT
void *
976 nci_piiii(int alpha
, int beta
, int gamma
, int delta
)
978 static struct array_container
990 container
.array
= my_array
;
997 =item C<PARROT_DYNEXT_EXPORT void * nci_pii(int fac1, int fac2)>
999 Returns the address of global variable C<nci_dlvar_int> whose value is set
1000 to the product of C<fac1 * fac2>.
1006 PARROT_DYNEXT_EXPORT
void *
1007 nci_pii(int fac1
, int fac2
)
1009 nci_dlvar_int
= fac1
* fac2
;
1011 return &nci_dlvar_int
;
1016 =item C<PARROT_DYNEXT_EXPORT void nci_v(void)>
1018 Multiplies the global variable C<nci_dlvar_int> times 10.
1024 PARROT_DYNEXT_EXPORT
void
1027 nci_dlvar_int
*= 10;
1032 =item C<PARROT_DYNEXT_EXPORT void nci_vv(void)>
1034 Multiplies the global variable C<nci_dlvar_int> by 3.
1040 PARROT_DYNEXT_EXPORT
void
1048 =item C<PARROT_DYNEXT_EXPORT void nci_vVi(Opaque **outOpaque, int x)>
1050 Test an NCI opaque struct out value.
1056 PARROT_DYNEXT_EXPORT
void
1057 nci_vVi(Opaque
**outOpaque
, int x
)
1059 static Opaque opaque
;
1061 *outOpaque
= &opaque
;
1066 =item C<PARROT_DYNEXT_EXPORT void nci_vp(Opaque *inOpaque)>
1068 Test that a previously generated opaque struct gets passed back
1069 to an NCI function correctly.
1075 PARROT_DYNEXT_EXPORT
void
1076 nci_vp(Opaque
*inOpaque
)
1079 printf("got %d\n", inOpaque
->x
);
1081 printf("got null\n");
1086 =item C<PARROT_DYNEXT_EXPORT char * nci_ttt(char *s1, char *s2)>
1088 Prints and returns "s2, s2, s1"
1094 PARROT_DYNEXT_EXPORT
char *
1095 nci_ttt(char *s1
, char *s2
)
1097 char* s
= (char*) malloc((2 * strlen(s2
)) + strlen(s1
) + 5);
1098 sprintf(s
, "%s, %s, %s", s2
, s2
, s1
);
1105 validate_float(float f
, double checkval
) {
1108 error_ratio
= (((double)f
) - checkval
) / checkval
;
1109 valid
= error_ratio
<= 0.01 && error_ratio
>= -0.01;
1110 printf("%i\n", valid
);
1115 =item C<PARROT_DYNEXT_EXPORT void nci_vfff(float l1, float l2, float l3)>
1117 Checks that C<[ l1, l2, l3 ]> = C<[ 3456.54, 10.1999, 14245.567 ]> within an
1124 PARROT_DYNEXT_EXPORT
void
1125 nci_vfff(float l1
, float l2
, float l3
)
1127 validate_float(l1
, 3456.54);
1128 validate_float(l2
, 10.1999);
1129 validate_float(l3
, 14245.567);
1135 =item C<PARROT_DYNEXT_EXPORT void nci_vV(const char **ptr)>
1137 Sets C<*ptr> to "Hello bright new world\n".
1143 PARROT_DYNEXT_EXPORT
void
1144 nci_vV(const char **ptr
)
1146 *ptr
= "Hello bright new world\n";
1151 =item C<PARROT_DYNEXT_EXPORT void nci_vVVV(const char **ptr1, const char **ptr2,
1154 Sets C<*ptr1> to "Hello bright new world!\n", C<*ptr2> to "It is a beautiful
1155 day!\n", and C<*ptr3> to "Go suck a lemon.\n".
1161 PARROT_DYNEXT_EXPORT
void
1162 nci_vVVV(const char **ptr1
, const char **ptr2
, const char **ptr3
)
1164 *ptr1
= "Hello bright new world!\n";
1165 *ptr2
= "It is a beautiful day!\n";
1166 *ptr3
= "Go suck a lemon.\n";
1176 =item C<int main(void)>
1178 Calls test functions C<nci_ssc> and C<nci_fff> and prints their results.
1189 int l
= nci_ssc(l1
, l2
);
1191 f
= nci_fff(f1
, f2
);
1209 F<docs/pdds/pdd16_native_call.pod>
1210 F<config/gen/makefiles/root.in>
1220 * c-file-style: "parrot"
1222 * vim: expandtab shiftwidth=4: