2 Copyright (C) 2001-2010, 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
167 return nci_dlvar_char
;
172 =item C<PARROT_DYNEXT_EXPORT char nci_csc(short l1, char l2)>
174 Multiplies C<l1> and C<l2> together and returns the first byte of the result.
181 PARROT_CONST_FUNCTION
183 nci_csc(short l1
, char l2
)
190 =item C<PARROT_DYNEXT_EXPORT double nci_d(void)>
192 Multiplies the current value of C<nci_dlvar_double> by 10.0, and returns
203 nci_dlvar_double
*= 10.0;
205 return nci_dlvar_double
;
210 =item C<PARROT_DYNEXT_EXPORT double nci_dd(double d)>
212 Returns the value C<d> multiplied by 2.0.
219 PARROT_CONST_FUNCTION
228 =item C<PARROT_DYNEXT_EXPORT float nci_f(void)>
230 Multiplies the value C<nci_dlvar_float> by 10.0 and returns the new
241 nci_dlvar_float
*= 10.0;
243 return nci_dlvar_float
;
248 =item C<PARROT_DYNEXT_EXPORT float nci_fff(float l1, float l2)>
250 Returns the result of C<l1> / C<l2>.
257 PARROT_CONST_FUNCTION
259 nci_fff(float l1
, float l2
)
266 =item C<PARROT_DYNEXT_EXPORT int nci_i(void)>
268 Returns the current value of <nci_dlvar_int>.
279 return nci_dlvar_int
;
284 =item C<PARROT_DYNEXT_EXPORT int nci_isc(short l1, char l2)>
286 Returns the int product of C<l1 * l2>.
293 PARROT_CONST_FUNCTION
295 nci_isc(short l1
, char l2
)
302 =item C<PARROT_DYNEXT_EXPORT int nci_ip(void *p)>
304 Performs a series of operations on values stored at pointer C<p>.
314 typedef struct _dfi
{
324 return (int) (sp
->d
+ sp
->f
+ sp
->i
);
329 =item C<PARROT_DYNEXT_EXPORT int nci_it(void *p)>
331 Prints the first two characters in C<p>, in reversed order. Returns 2.
341 fprintf(stderr
, "%c%c\n", ((char*) p
)[1], ((char *) p
)[0]);
349 =item C<PARROT_DYNEXT_EXPORT long nci_l(void)>
351 Returns the value of C<nci_dlvar_long>.
362 return nci_dlvar_long
;
367 =item C<PARROT_DYNEXT_EXPORT int * nci_p(void)>
369 Returns the address of C<nci_dlvar_int>.
376 PARROT_CONST_FUNCTION
380 return &nci_dlvar_int
;
385 =item C<PARROT_DYNEXT_EXPORT char * nci_t(void)>
387 Returns the value of C<nci_dlvar_cstring>.
394 PARROT_CONST_FUNCTION
398 return nci_dlvar_cstring
;
403 =item C<PARROT_DYNEXT_EXPORT char * nci_tb(void *p)>
405 Returns "xx worked", where "xx" is replaced with the first two character values
406 of C<p>, in reverse order.
412 static char b
[] = "xx worked\n";
418 b
[0] = ((char*) p
)[1];
419 b
[1] = ((char*) p
)[0];
426 =item C<PARROT_DYNEXT_EXPORT char * nci_tt(char *p)>
428 Returns "xx worked", where "xx" is replaced with the first two character values
429 of C<p>, in reverse order.
435 static char s
[] = "xx worked\n";
449 =item C<PARROT_DYNEXT_EXPORT char * nci_tB(void **p)>
451 Returns "xx done", where "xx" is replaced with the first two character values
452 of C<p>, in reverse order.
458 static char B
[] = "xx done\n";
464 B
[0] = (*(char**) p
)[1];
465 B
[1] = (*(char**) p
)[0];
472 =item C<PARROT_DYNEXT_EXPORT void * nci_pp(void *p)>
474 Returns the value C<p> directly.
481 PARROT_CONST_FUNCTION
490 =item C<PARROT_DYNEXT_EXPORT int nci_iiii(int i1, int i2, int i3)>
492 Prints three integers separated by whitespace to C<stderr>.
501 nci_iiii(int i1
, int i2
, int i3
)
503 fprintf(stderr
, "%d %d %d\n", i1
, i2
, i3
);
511 =item C<PARROT_DYNEXT_EXPORT int nci_i4i(long * l, int i)>
513 Returns the product of C<*l> and C<i>, as an int.
522 nci_i4i(long * l
, int i
)
525 return (int) (*l
* i
);
530 =item C<PARROT_DYNEXT_EXPORT int nci_ii3(int a, int *bp)>
532 Multiplies C<a> and C<*bp> together and returns the result. Updates C<*bp>
541 nci_ii3(int a
, int *bp
)
551 =item C<PARROT_DYNEXT_EXPORT int call_back(const char *str)>
553 writes the string C<str> to stdout and returns the value 4711.
561 call_back(const char *str
)
571 =item C<PARROT_DYNEXT_EXPORT void * nci_pi(int test)>
573 Performs one from a series of tests, depending on the value given for C<test>.
634 } xx
= { 100, 77, 200.0 };
647 int (*f
)(const char *);
706 static int i
= 55555;
712 fprintf(stderr
, "unknown test number\n");
720 =item C<PARROT_DYNEXT_EXPORT short nci_s(void)>
722 Returns the value of C<nci_dlvar_short>.
733 return nci_dlvar_short
;
738 =item C<PARROT_DYNEXT_EXPORT short nci_ssc(short l1, char l2)>
740 Returns the product of C<l1 * l2>.
747 PARROT_CONST_FUNCTION
749 nci_ssc(short l1
, char l2
)
756 =item C<PARROT_DYNEXT_EXPORT void nci_vP(void *pmc)>
758 Prints "ok" if C<PMC> is not null, prints "got null" otherwise.
769 * Disable this test until someone figures a way to check for
770 * PMCNULL without using libparrot.
771 if (!PMC_IS_NULL(pmc))
783 =head2 Functions used for pdd16 tests
793 =item C<PARROT_DYNEXT_EXPORT void nci_cb_C1(cb_C1_func cb, void* user_data)>
795 Calls C<cb> function with the string "result" and the given C<user_data>.
804 nci_cb_C1(cb_C1_func cb
, void* user_data
)
806 const char *result
= "succeeded";
807 /* call the cb synchronously */
808 (cb
)(result
, user_data
);
815 =item C<PARROT_DYNEXT_EXPORT void nci_cb_C2(cb_C2_func cb, void* user_data)>
817 Calls the function C<cb> with the integer 77 and the given C<user_data>.
826 nci_cb_C2(cb_C2_func cb
, void* user_data
)
828 /* call the cb synchronously */
836 =item C<PARROT_DYNEXT_EXPORT void nci_cb_C3(cb_C3_func cb, void* user_data)>
838 Calls function C<cb> with C<&int_cb_C3> and the givn C<user_data>.
845 static int int_cb_C3
= 99;
849 nci_cb_C3(cb_C3_func cb
, void* user_data
)
851 /* call the cb synchronously */
852 (cb
)(&int_cb_C3
, user_data
);
859 =item C<PARROT_DYNEXT_EXPORT void nci_cb_D1(cb_D1_func cb, void* user_data)>
861 Calls function C<cb> with data C<user_data> and the string "succeeded".
870 nci_cb_D1(cb_D1_func cb
, void* user_data
)
872 const char *result
= "succeeded";
873 /* call the cb synchronously */
874 (cb
)(user_data
, result
);
881 =item C<PARROT_DYNEXT_EXPORT void nci_cb_D2(cb_D2_func cb, void* user_data)>
883 Calls function C<cb> with data C<user_data> and the integer 88.
892 nci_cb_D2(cb_D2_func cb
, void* user_data
)
894 /* call the cb synchronously */
902 =item C<PARROT_DYNEXT_EXPORT void nci_cb_D3(cb_D3_func cb, void* user_data)>
904 Calls function C<cb> with data C<user_data> and C<&int_cb_D3>.
911 static int int_cb_D3
= 111;
915 nci_cb_D3(cb_D3_func cb
, void* user_data
)
917 /* call the cb synchronously */
918 (cb
)(user_data
, &int_cb_D3
);
925 =item C<PARROT_DYNEXT_EXPORT void nci_cb_D4(cb_D4_func times_ten, void*
928 Calls function C<times_ten> with data C<user_data> and C<&int_cb_D4> 10 times
929 in a loop, incrementing C<int_cb_D4> after every call.
938 nci_cb_D4(cb_D4_func times_ten
, void* user_data
)
941 for (cnt
= 0; cnt
< 9; ++cnt
)
943 (times_ten
)(user_data
, &int_cb_D4
);
952 =item C<PARROT_DYNEXT_EXPORT void nci_pip(int count, Rect_Like *rects)>
954 Prints a count integer and the coordinates of 4 rectangles.
962 nci_pip(int count
, Rect_Like
*rects
)
965 printf("Count: %d\n", count
);
966 for (i
= 0; i
< 4; ++i
)
967 printf("X: %d\nY: %d\nW: %d\nH: %d\n",
968 rects
[i
].x
, rects
[i
].y
, rects
[i
].w
, rects
[i
].h
);
973 =item C<PARROT_DYNEXT_EXPORT int nci_i33(int *double_me, int *triple_me)>
975 Doubles C<double_me> and triples C<triple_me>. Returns their sum.
983 nci_i33(ARGMOD(int *double_me
), ARGMOD(int *triple_me
))
988 return (*double_me
+ *triple_me
);
993 =item C<PARROT_DYNEXT_EXPORT void nci_vpii(Outer *my_data, int my_x, int my_y)>
995 Updates data in structure pointer C<my_data> with the given data C<my_x> and
1002 PARROT_DYNEXT_EXPORT
1004 nci_vpii(ARGMOD(Outer
*my_data
), int my_x
, int my_y
)
1007 my_data
->nested
->y
= my_y
;
1012 =item C<PARROT_DYNEXT_EXPORT void * nci_piiii(int alpha, int beta, int gamma,
1015 Stores 4 integer values into an array structure, and returns the address
1022 static int my_array
[4];
1024 PARROT_DYNEXT_EXPORT
1026 nci_piiii(int alpha
, int beta
, int gamma
, int delta
)
1028 static struct array_container
1034 my_array
[0] = alpha
;
1036 my_array
[2] = gamma
;
1037 my_array
[3] = delta
;
1040 container
.array
= my_array
;
1047 =item C<PARROT_DYNEXT_EXPORT void * nci_pii(int fac1, int fac2)>
1049 Returns the address of global variable C<nci_dlvar_int> whose value is set
1050 to the product of C<fac1 * fac2>.
1056 PARROT_DYNEXT_EXPORT
1058 nci_pii(int fac1
, int fac2
)
1060 nci_dlvar_int
= fac1
* fac2
;
1062 return &nci_dlvar_int
;
1067 =item C<PARROT_DYNEXT_EXPORT void nci_v(void)>
1069 Multiplies the global variable C<nci_dlvar_int> times 10.
1075 PARROT_DYNEXT_EXPORT
1079 nci_dlvar_int
*= 10;
1084 =item C<PARROT_DYNEXT_EXPORT void nci_vv(void)>
1086 Multiplies the global variable C<nci_dlvar_int> by 3.
1092 PARROT_DYNEXT_EXPORT
1101 =item C<PARROT_DYNEXT_EXPORT void nci_vVi(Opaque **outOpaque, int x)>
1103 Test an NCI opaque struct out value.
1109 PARROT_DYNEXT_EXPORT
1111 nci_vVi(ARGOUT(Opaque
**outOpaque
), int x
)
1113 static Opaque opaque
;
1115 *outOpaque
= &opaque
;
1120 =item C<PARROT_DYNEXT_EXPORT void nci_vp(Opaque *inOpaque)>
1122 Test that a previously generated opaque struct gets passed back
1123 to an NCI function correctly.
1129 PARROT_DYNEXT_EXPORT
1131 nci_vp(ARGIN(Opaque
*inOpaque
))
1134 printf("got %d\n", inOpaque
->x
);
1136 printf("got null\n");
1141 =item C<PARROT_DYNEXT_EXPORT char * nci_ttt(char *s1, char *s2)>
1143 Prints and returns "s2, s2, s1"
1149 PARROT_DYNEXT_EXPORT
1151 nci_ttt(char *s1
, char *s2
)
1153 char* s
= (char*) malloc((2 * strlen(s2
)) + strlen(s1
) + 5);
1154 sprintf(s
, "%s, %s, %s", s2
, s2
, s1
);
1161 =item C<static void validate_float(float f, double checkval)>
1163 Check that a float value f is has an error ratio of less than 0.01
1164 when compared to a double value checkval
1171 validate_float(float f
, double checkval
)
1175 error_ratio
= (((double)f
) - checkval
) / checkval
;
1176 valid
= error_ratio
<= 0.01 && error_ratio
>= -0.01;
1177 printf("%i\n", valid
);
1182 =item C<PARROT_DYNEXT_EXPORT void nci_vfff(float l1, float l2, float l3)>
1184 Checks that C<[ l1, l2, l3 ]> = C<[ 3456.54, 10.1999, 14245.567 ]> within an
1191 PARROT_DYNEXT_EXPORT
1193 nci_vfff(float l1
, float l2
, float l3
)
1195 validate_float(l1
, 3456.54);
1196 validate_float(l2
, 10.1999);
1197 validate_float(l3
, 14245.567);
1203 =item C<PARROT_DYNEXT_EXPORT void nci_vV(const char **ptr)>
1205 Sets C<*ptr> to "Hello bright new world\n".
1211 PARROT_DYNEXT_EXPORT
1213 nci_vV(const char **ptr
)
1215 *ptr
= "Hello bright new world\n";
1220 =item C<PARROT_DYNEXT_EXPORT void nci_vVVV(const char **ptr1, const char **ptr2,
1223 Sets C<*ptr1> to "Hello bright new world!\n", C<*ptr2> to "It is a beautiful
1224 day!\n", and C<*ptr3> to "Go suck a lemon.\n".
1230 PARROT_DYNEXT_EXPORT
1232 nci_vVVV(const char **ptr1
, const char **ptr2
, const char **ptr3
)
1234 *ptr1
= "Hello bright new world!\n";
1235 *ptr2
= "It is a beautiful day!\n";
1236 *ptr3
= "Go suck a lemon.\n";
1246 =item C<int main(void)>
1248 Calls test functions C<nci_ssc> and C<nci_fff> and prints their results.
1259 int l
= nci_ssc(l1
, l2
);
1261 f
= nci_fff(f1
, f2
);
1279 F<docs/pdds/pdd16_native_call.pod>
1280 F<config/gen/makefiles/root.in>
1290 * c-file-style: "parrot"
1292 * vim: expandtab shiftwidth=4: