[TT #871] Add rand as a dynop, with tests
[parrot.git] / src / nci_test.c
blob8fa232fca8b0ad6150fb853d155a86c688c3bbcd
1 /*
2 Copyright (C) 2001-2007, Parrot Foundation.
3 $Id$
5 =head1 NAME
7 src/nci_test.c - shared library used for testing the Native Call Interface
9 =head1 DESCRIPTION
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'.
25 =head2 Functions
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'.
30 =over 4
32 =cut
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <parrot/config.h>
41 #ifdef __cplusplus
42 extern "C" {
43 #endif
46 /* Declarations of structs */
48 typedef struct Nested {
49 int y;
50 } Nested;
52 typedef struct Outer {
53 int x;
54 Nested *nested;
55 } Outer;
57 typedef struct Rect_Like {
58 int x, y;
59 int w, h;
60 } Rect_Like;
62 typedef struct Opaque {
63 int x;
64 } Opaque;
66 /* Function declarations.
68 *** If you add a new test function here,
69 *** please update src/libnci_test.def and src/call_list.txt too. ***
73 PARROT_EXPORT int call_back(const char *str);
74 PARROT_EXPORT char nci_c(void);
75 PARROT_EXPORT char nci_csc(short, char);
76 PARROT_EXPORT double nci_d(void);
77 PARROT_EXPORT double nci_dd(double);
78 PARROT_EXPORT float nci_f(void);
79 PARROT_EXPORT float nci_fff(float, float);
80 PARROT_EXPORT int nci_i(void);
81 PARROT_EXPORT int nci_ib(int *);
82 PARROT_EXPORT int nci_iiii(int, int, int);
83 PARROT_EXPORT int nci_ii3(int, int *);
84 PARROT_EXPORT int nci_ip(void *);
85 PARROT_EXPORT int nci_isc(short, char);
86 PARROT_EXPORT int nci_it(void *);
87 PARROT_EXPORT int nci_i33(int *, int *);
88 PARROT_EXPORT int nci_i4i(long *, int);
89 PARROT_EXPORT long nci_l(void);
90 PARROT_EXPORT int * nci_p(void);
91 PARROT_EXPORT void * nci_pi(int);
92 PARROT_EXPORT void * nci_pii(int, int);
93 PARROT_EXPORT void * nci_piiii(int, int, int, int);
94 PARROT_EXPORT void nci_pip(int, Rect_Like *);
95 PARROT_EXPORT void * nci_pp(void *);
96 PARROT_EXPORT short nci_s(void);
97 PARROT_EXPORT short nci_ssc(short, char);
98 PARROT_EXPORT char * nci_t(void);
99 PARROT_EXPORT char * nci_tb(void *);
100 PARROT_EXPORT char * nci_tB(void **);
101 PARROT_EXPORT char * nci_tt(void *);
102 PARROT_EXPORT void nci_v(void);
103 PARROT_EXPORT void nci_vP(void *);
104 PARROT_EXPORT void nci_vpii(Outer *, int, int);
105 PARROT_EXPORT void nci_vv(void);
106 PARROT_EXPORT void nci_vVi(Opaque**, int);
107 PARROT_EXPORT void nci_vp(Opaque*);
108 PARROT_EXPORT char * nci_ttt(char *, char *);
109 PARROT_EXPORT void nci_vfff(float, float, float);
110 PARROT_EXPORT void nci_vV(const char **);
111 PARROT_EXPORT void nci_vVVV(const char **, const char **, const char **);
113 /* Declarations for callback tests */
115 typedef void (*cb_C1_func)(const char*, void*);
116 PARROT_EXPORT void nci_cb_C1(cb_C1_func, void*);
118 typedef void (*cb_C2_func)(int, void*);
119 PARROT_EXPORT void nci_cb_C2(cb_C2_func, void*);
121 typedef void (*cb_C3_func)(void*, void*);
122 PARROT_EXPORT void nci_cb_C3(cb_C3_func, void*);
124 typedef void (*cb_D1_func)(void*, const char*);
125 PARROT_EXPORT void nci_cb_D1(cb_D1_func, void*);
127 typedef void (*cb_D2_func)(void*, int);
128 PARROT_EXPORT void nci_cb_D2(cb_D2_func, void*);
130 typedef void (*cb_D3_func)(void*, void*);
131 PARROT_EXPORT void nci_cb_D3(cb_D3_func, void*);
133 typedef void (*cb_D4_func)(void*, void*);
134 PARROT_EXPORT void nci_cb_D4(cb_D4_func, void*);
136 /* Variable definitions */
138 PARROT_EXPORT int int_cb_D4 = -55555;
139 PARROT_EXPORT int nci_dlvar_char = 22;
140 PARROT_EXPORT int nci_dlvar_short = 333;
141 PARROT_EXPORT int nci_dlvar_int = -4444;
142 PARROT_EXPORT long nci_dlvar_long = -7777777;
143 PARROT_EXPORT float nci_dlvar_float = -333.0;
144 PARROT_EXPORT double nci_dlvar_double = -55555.55555;
145 PARROT_EXPORT char nci_dlvar_cstring[] = "This is a C-string.\n";
148 /* Function definitions */
152 =item C<PARROT_EXPORT char
153 nci_c(void)>
155 Returns the value of the variable C<nci_dlvar_char>, which is set to 22 by
156 default.
158 =cut
162 PARROT_EXPORT char
163 nci_c(void) {
164 return nci_dlvar_char;
169 =item C<PARROT_EXPORT char
170 nci_csc(short l1, char l2)>
172 Multiplies C<l1> and C<l2> together and returns the first byte of the result.
174 =cut
178 PARROT_EXPORT char
179 nci_csc(short l1, char l2)
181 return l1 * l2;
186 =item C<PARROT_EXPORT double
187 nci_d(void)>
189 Multiplies the current value of C<nci_dlvar_double> by 10.0, and returns
190 the new value.
192 =cut
196 PARROT_EXPORT double
197 nci_d(void)
199 nci_dlvar_double *= 10.0;
201 return nci_dlvar_double;
206 =item C<PARROT_EXPORT double
207 nci_dd(double d)>
209 Returns the value C<d> multiplied by 2.0.
211 =cut
215 PARROT_EXPORT double
216 nci_dd(double d)
218 return d * 2.0;
223 =item C<PARROT_EXPORT float
224 nci_f(void)>
226 Multiplies the value C<nci_dlvar_float> by 10.0 and returns the new
227 value.
229 =cut
233 PARROT_EXPORT float
234 nci_f(void)
236 nci_dlvar_float *= 10.0;
238 return nci_dlvar_float;
243 =item C<PARROT_EXPORT float
244 nci_fff(float l1, float l2)>
246 Returns the result of C<l1> / C<l2>.
248 =cut
252 PARROT_EXPORT float
253 nci_fff(float l1, float l2)
255 return l1 / l2;
260 =item C<PARROT_EXPORT int
261 nci_i(void)>
263 Returns the current value of <nci_dlvar_int>.
265 =cut
269 PARROT_EXPORT int
270 nci_i(void)
272 return nci_dlvar_int;
277 =item C<PARROT_EXPORT int
278 nci_isc(short l1, char l2)>
280 Returns the int product of C<l1 * l2>.
282 =cut
286 PARROT_EXPORT int
287 nci_isc(short l1, char l2)
289 return l1 * l2;
294 =item C<PARROT_EXPORT int
295 nci_ip(void *p)>
297 Performs a series of operations on values stored at pointer C<p>.
299 =cut
303 PARROT_EXPORT int
304 nci_ip(void *p)
306 typedef struct _dfi {
307 double d;
308 float f;
309 int i;
310 char *s;
311 } dfi;
312 dfi *sp = (dfi*) p;
313 puts(sp->s);
314 fflush(stdout);
316 return (int) (sp->d + sp->f + sp->i);
321 =item C<PARROT_EXPORT int
322 nci_it(void *p)>
324 test calls this with a string
326 =cut
330 PARROT_EXPORT int
331 nci_it(void *p)
333 fprintf(stderr, "%c%c\n", ((char*) p)[1], ((char *) p)[0]);
334 fflush(stderr);
336 return 2;
341 =item C<PARROT_EXPORT long
342 nci_l(void)>
344 Returns the value of C<nci_dlvar_long>.
346 =cut
350 PARROT_EXPORT long
351 nci_l(void)
353 return nci_dlvar_long;
358 =item C<PARROT_EXPORT int *
359 nci_p(void)>
361 Returns the address of C<nci_dlvar_int>.
363 =cut
367 PARROT_EXPORT int *
368 nci_p(void)
370 return &nci_dlvar_int;
375 =item C<PARROT_EXPORT char *
376 nci_t(void)>
378 Returns the value of C<nci_dlvar_cstring>.
380 =cut
384 PARROT_EXPORT char *
385 nci_t(void)
387 return nci_dlvar_cstring;
392 =item C<PARROT_EXPORT char *
393 nci_tb(void *p)>
395 Prints "xx worked", where "xx" is replaced with the first two character values
396 of C<p>, in reverse order.
398 =cut
402 static char b[] = "xx worked\n";
404 PARROT_EXPORT char *
405 nci_tb(void *p)
407 b[0] = ((char*) p)[1];
408 b[1] = ((char*) p)[0];
410 return b;
415 =item C<PARROT_EXPORT char *
416 nci_tt(void *p)>
418 Prints "xx worked", where "xx" is replaced with the first two character values
419 of C<p>, in reverse order.
421 =cut
425 static char s[] = "xx worked\n";
427 PARROT_EXPORT char *
428 nci_tt(void *p)
430 s[0] = ((char*) p)[1];
431 s[1] = ((char*) p)[0];
433 return s;
438 =item C<PARROT_EXPORT char *
439 nci_tB(void **p)>
441 Prints "xx done", where "xx" is replaced with the first two character values
442 of C<p>, in reverse order.
444 =cut
448 static char B[] = "xx done\n";
450 PARROT_EXPORT char *
451 nci_tB(void **p)
453 B[0] = (*(char**) p)[1];
454 B[1] = (*(char**) p)[0];
456 return B;
461 =item C<PARROT_EXPORT void *
462 nci_pp(void *p)>
464 Returns the value C<p> directly.
466 =cut
470 PARROT_EXPORT void *
471 nci_pp(void *p)
473 return p;
478 =item C<PARROT_EXPORT int
479 nci_iiii(int i1, int i2, int i3)>
481 Prints three integers separated by whitespace to C<stderr>.
483 =cut
487 PARROT_EXPORT int
488 nci_iiii(int i1, int i2, int i3)
490 fprintf(stderr, "%d %d %d\n", i1, i2, i3);
491 fflush(stderr);
493 return 2;
498 =item C<PARROT_EXPORT int
499 nci_i4i(long * l, int i)>
501 Returns the product of C<*l> and C<i>, as an int.
503 =cut
507 PARROT_EXPORT int
508 nci_i4i(long * l, int i)
511 return (int) (*l * i);
516 =item C<PARROT_EXPORT int
517 nci_ii3(int a, int *bp)>
519 Multiplies C<a> and C<*bp> together and returns the result. Updates C<*bp>
520 to the value 4711.
522 =cut
526 PARROT_EXPORT int
527 nci_ii3(int a, int *bp)
529 int r = a * *bp;
530 *bp = 4711;
532 return r;
537 =item C<PARROT_EXPORT int
538 call_back(const char *str)>
540 writes the string C<str> to stdout and returns the value 4711.
542 =cut
546 PARROT_EXPORT int
547 call_back(const char *str)
549 puts(str);
550 fflush(stdout);
552 return 4711;
557 =item C<PARROT_EXPORT void *
558 nci_pi(int test)>
560 Performs one from a series of tests, depending on the value given for C<test>.
562 =cut
566 PARROT_EXPORT void *
567 nci_pi(int test)
569 switch (test) {
570 case 0:
572 static struct {
573 int i[2];
574 char c;
575 } t = {
576 {42, 100},
579 return &t;
581 case 1:
583 static struct {
584 float f[2];
585 double d;
586 } t = {
587 {42.0, 100.0},
588 47.11
590 return &t;
592 case 2:
594 static struct {
595 char c;
596 int i;
597 } t = {
601 return &t;
603 case 3:
605 static struct {
606 const char *c;
607 int i;
608 } t = {
609 "hello",
612 return &t;
614 case 4:
616 static struct _x {
617 int i;
618 int j;
619 double d;
620 } xx = { 100, 77, 200.0 };
621 static struct {
622 char c;
623 struct _x *x;
624 } t = {
628 return &t;
630 case 5:
632 static struct {
633 int (*f)(const char *);
634 } t = {
635 call_back
637 return &t;
639 case 6:
641 static struct xt {
642 int x;
643 struct yt {
644 int i;
645 int j;
646 } _y;
647 int z;
648 } _x = {
650 { 127, 12345 },
653 return &_x;
655 case 7:
657 static struct xt {
658 char x;
659 struct yt {
660 char i;
661 int j;
662 } _y;
663 char z;
664 } _x = {
666 { 127, 12345 },
669 return &_x;
671 case 8:
673 static struct _z {
674 int i;
675 int j;
676 } zz = { 100, 77 };
677 static struct xt {
678 int x;
679 struct yt {
680 int i;
681 int j;
682 struct _z *z;
683 } _y;
684 } _x = {
686 { 127, 12345, &zz },
688 return &_x;
690 case 9:
692 static int i = 55555;
693 return &i;
695 default:
696 fprintf(stderr, "unknown test number\n");
699 return NULL;
704 =item C<PARROT_EXPORT short
705 nci_s(void)>
707 Returns the value of C<nci_dlvar_short>.
709 =cut
713 PARROT_EXPORT short
714 nci_s(void)
716 return nci_dlvar_short;
721 =item C<PARROT_EXPORT short
722 nci_ssc(short l1, char l2)>
724 Returns the product of C<l1 * l2>.
726 =cut
730 PARROT_EXPORT short
731 nci_ssc(short l1, char l2)
733 return l1 * l2;
738 =item C<PARROT_EXPORT void
739 nci_vP(void *pmc)>
741 Prints "ok" if C<PMC> is not null, prints "got null" otherwise.
743 =cut
747 PARROT_EXPORT void
748 nci_vP(void *pmc)
750 if (pmc)
751 puts("ok");
752 else
753 puts("got null");
759 =back
761 =head2 Functions used for pdd16 tests
763 =over 4
765 =cut
771 =item C<PARROT_EXPORT void
772 nci_cb_C1(cb_C1_func cb, void* user_data)>
774 Calls C<cb> function with the string "result" and the given C<user_data>.
775 No return value.
777 =cut
781 PARROT_EXPORT void
782 nci_cb_C1(cb_C1_func cb, void* user_data)
784 const char *result = "succeeded";
785 /* call the cb synchronously */
786 (cb)(result, user_data);
788 return;
793 =item C<PARROT_EXPORT void
794 nci_cb_C2(cb_C2_func cb, void* user_data)>
796 Calls the function C<cb> with the pointer C<user_data>. No return value.
798 =cut
802 PARROT_EXPORT void
803 nci_cb_C2(cb_C2_func cb, void* user_data)
805 /* call the cb synchronously */
806 (cb)(77, user_data);
808 return;
813 =item C<PARROT_EXPORT void
814 nci_cb_C3(cb_C3_func cb, void* user_data)>
816 Calls function C<cb> with data C<user_data>. No return value.
818 =cut
822 static int int_cb_C3 = 99;
824 PARROT_EXPORT void
825 nci_cb_C3(cb_C3_func cb, void* user_data)
827 /* call the cb synchronously */
828 (cb)(&int_cb_C3, user_data);
830 return;
835 =item C<PARROT_EXPORT void
836 nci_cb_D1(cb_D1_func cb, void* user_data)>
838 Calls function C<cb> with data C<user_data>. No return value.
840 =cut
844 PARROT_EXPORT void
845 nci_cb_D1(cb_D1_func cb, void* user_data)
847 const char *result = "succeeded";
848 /* call the cb synchronously */
849 (cb)(user_data, result);
851 return;
856 =item C<PARROT_EXPORT void
857 nci_cb_D2(cb_D2_func cb, void* user_data)>
859 Calls function C<cb> with data C<user_data>.
861 =cut
865 PARROT_EXPORT void
866 nci_cb_D2(cb_D2_func cb, void* user_data)
868 /* call the cb synchronously */
869 (cb)(user_data, 88);
871 return;
876 =item C<PARROT_EXPORT void
877 nci_cb_D3(cb_D3_func cb, void* user_data)>
879 Calls function C<cb> with data C<user_data>.
881 =cut
885 static int int_cb_D3 = 111;
887 PARROT_EXPORT void
888 nci_cb_D3(cb_D3_func cb, void* user_data)
890 /* call the cb synchronously */
891 (cb)(user_data, &int_cb_D3);
893 return;
898 =item C<PARROT_EXPORT void
899 nci_cb_D4(cb_D4_func times_ten, void* user_data)>
901 Calls function C<times_ten> with data C<user_data> 10 times in a loop.
903 =cut
907 PARROT_EXPORT void
908 nci_cb_D4(cb_D4_func times_ten, void* user_data)
910 int cnt;
911 for (cnt = 0; cnt < 9; cnt++)
913 (times_ten)(user_data, &int_cb_D4);
914 int_cb_D4++;
917 return;
922 =item C<PARROT_EXPORT void
923 nci_pip(int count, Rect_Like *rects)>
925 Prints a count integer and the coordinates of 4 rectangles.
927 =cut
931 PARROT_EXPORT void
932 nci_pip(int count, Rect_Like *rects)
934 int i;
935 printf("Count: %d\n", count);
936 for (i = 0; i < 4; ++i)
937 printf("X: %d\nY: %d\nW: %d\nH: %d\n",
938 rects[i].x, rects[i].y, rects[i].w, rects[i].h);
943 =item C<PARROT_EXPORT int
944 nci_i33(int *double_me, int *triple_me)>
946 Returns the result C<*double_me * 2 + *triple_me * 3>.
948 =cut
952 PARROT_EXPORT int
953 nci_i33(int *double_me, int *triple_me)
955 *double_me *= 2;
956 *triple_me *= 3;
958 return (*double_me + *triple_me);
963 =item C<PARROT_EXPORT void
964 nci_vpii(Outer *my_data, int my_x, int my_y)>
966 Updates data in structure pointer C<my_data> with the given data C<my_x> and
967 C<my_y>.
969 =cut
973 PARROT_EXPORT void
974 nci_vpii(Outer *my_data, int my_x, int my_y)
976 my_data->x = my_x;
977 my_data->nested->y = my_y;
982 =item C<PARROT_EXPORT void *
983 nci_piiii(int alpha, int beta, int gamma, int delta)>
985 Stores 4 integer values into an array structure, and returns the address
986 of that structure.
988 =cut
992 static int my_array[4];
994 PARROT_EXPORT void *
995 nci_piiii(int alpha, int beta, int gamma, int delta)
997 static struct array_container
999 int x;
1000 int *array;
1001 } container;
1003 my_array[0] = alpha;
1004 my_array[1] = beta;
1005 my_array[2] = gamma;
1006 my_array[3] = delta;
1008 container.x = 4;
1009 container.array = my_array;
1011 return &container;
1016 =item C<PARROT_EXPORT void *
1017 nci_pii(int fac1, int fac2)>
1019 Returns the address of global variable C<nci_dlvar_int> whose value is set
1020 to the product of C<fac1 * fac2>.
1022 =cut
1026 PARROT_EXPORT void *
1027 nci_pii(int fac1, int fac2)
1029 nci_dlvar_int = fac1 * fac2;
1031 return &nci_dlvar_int;
1036 =item C<PARROT_EXPORT void
1037 nci_v(void)>
1039 Multiplies the global variable C<nci_dlvar_int> times 10.
1041 =cut
1045 PARROT_EXPORT void
1046 nci_v(void)
1048 nci_dlvar_int *= 10;
1053 =item C<PARROT_EXPORT void
1054 nci_vv(void)>
1056 Multiplies the global variable C<nci_dlvar_int> by 3.
1058 =cut
1062 PARROT_EXPORT void
1063 nci_vv(void)
1065 nci_dlvar_int *= 3;
1070 =item C<PARROT_EXPORT void
1071 nci_vVi(Opaque**, int)>
1073 Test an NCI opaque struct out value.
1075 =cut
1079 PARROT_EXPORT void
1080 nci_vVi(Opaque **outOpaque, int x)
1082 static Opaque opaque;
1083 opaque.x = x;
1084 *outOpaque = &opaque;
1089 =item C<PARROT_EXPORT int
1090 nci_vp(Opaque*)>
1092 Test that a previously generated opaque struct gets passed back
1093 to an NCI function correctly.
1095 =cut
1099 PARROT_EXPORT void
1100 nci_vp(Opaque *inOpaque)
1102 if (inOpaque)
1103 printf("got %d\n", inOpaque->x);
1104 else
1105 printf("got null");
1110 =item C<PARROT_EXPORT char *
1111 nci_ttt(void *p)>
1113 Prints "s2, s1, s1d"
1115 =cut
1119 PARROT_EXPORT char *
1120 nci_ttt(char *s1, char *s2)
1122 char* s = (char*) malloc(strlen(s2) + (2 * strlen(s1)) + 5);
1123 sprintf(s, "%s, %s, %s", s2, s2, s1);
1124 printf("%s\n", s);
1125 return s;
1129 static void validate_float(float f, double checkval) {
1130 int valid;
1131 double error_ratio;
1132 error_ratio = (((double)f) - checkval) / checkval;
1133 valid = error_ratio <= 0.01 && error_ratio >= -0.01;
1134 printf("%i\n", valid);
1139 =item C<PARROT_EXPORT float
1140 nci_fff(float l1, float l2)>
1142 Returns the result of C<l1> / C<l2>.
1144 =cut
1148 PARROT_EXPORT void
1149 nci_vfff(float l1, float l2, float l3)
1151 validate_float(l1, 3456.54);
1152 validate_float(l2, 10.1999);
1153 validate_float(l3, 14245.567);
1159 =item C<PARROT_EXPORT float
1160 nci_fff(float l1, float l2)>
1162 Returns the result of C<l1> / C<l2>.
1164 =cut
1168 PARROT_EXPORT void
1169 nci_vV(const char **ptr)
1171 *ptr = "Hello bright new world\n";
1176 =item C<PARROT_EXPORT float
1177 nci_fff(float l1, float l2)>
1179 Returns the result of C<l1> / C<l2>.
1181 =cut
1185 PARROT_EXPORT void
1186 nci_vVVV(const char **ptr1, const char **ptr2, const char **ptr3)
1188 *ptr1 = "Hello bright new world!\n";
1189 *ptr2 = "It is a beautiful day!\n";
1190 *ptr3 = "Go suck a lemon.\n";
1193 #ifdef TEST
1195 char l2 = 4;
1196 float f2 = 4.0;
1200 =item C<int
1201 main(void)>
1203 Calls test functions C<nci_ssc> and C<nci_fff> and prints their results.
1205 =cut
1210 main(void)
1212 short l1 = 3;
1213 float f, f1 = 3.0;
1214 int l = nci_ssc(l1, l2);
1215 printf("%d\n", l);
1216 f = nci_fff(f1, f2);
1217 printf("%f\n", f);
1219 return 0;
1222 #endif
1224 #ifdef __cplusplus
1226 #endif
1230 =back
1232 =head1 SEE ALSO:
1234 F<docs/pdds/pdd16_native_call.pod>
1235 F<config/gen/makefiles/root.in>
1236 F<t/pmc/nci.t>
1238 =cut
1244 * Local variables:
1245 * c-file-style: "parrot"
1246 * End:
1247 * vim: expandtab shiftwidth=4: