1 /* Example code for a C-library accessible from ML
2 using the CInterface structure.
3 
4 Copyright David C.J. Matthews 1999, 2009, 2015
5 
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License version 2.1 as published by the Free Software Foundation.
9 
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 Lesser General Public License for more details.
14 
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18 */
19 /*
20 Linux: cc -shared -o Foreign ForeignTest.c
21 Windows: cl /MT ForeignTest.c /link /dll /out:Foreign.dll /def:Foreign.def
22 Mac OS X : cc -dynamiclib -o Foreign.dylib ForeignTest.c
23 */
24 #include <stdlib.h>
25 #include <string.h>
26 #include <stdio.h>
27 
28 /* Return a string duplicated n Times. */
DupNString(int n,char * str)29 char *DupNString(int n, char *str)
30 {
31     int nSize = strlen(str);
32     char *res = malloc(n*nSize + 1);
33     int i;
34     *res = 0;
35     for (i = 0; i < n; i++) strcat(res, str);
36     return res;
37 }
38 typedef struct _tree {
39     struct _tree *left, *right;
40     int	nValue;
41 } *tree;
42 
SumTree(tree t)43 int SumTree(tree t)
44 {
45     if (t == NULL) return 0;
46     else return t->nValue + SumTree(t->left) + SumTree(t->right);
47 }
48 
49 /* Tests to see whether small structures are returned specially. */
50 struct r2 { int n, m; };
51 
ReturnR2(int n,int m)52 struct r2 ReturnR2(int n, int m)
53 {
54     struct r2 ret;
55     ret.n = n + 1;
56     ret.m = m + 1;
57     return ret;
58 }
59 
60 // The SysV ABI for X64 Unix puts these in RAX/XMM0.
61 struct r4 {
62     int a, b;
63     float c, d;
64 };
65 
ReturnR4(int n,int m)66 struct r4 ReturnR4(int n, int m)
67 {
68     struct r4 ret;
69     ret.a = n + 1;
70     ret.b = m + 1;
71     ret.c = n + 2;
72     ret.d = m + 2;
73     return ret;
74 }
75 
76 struct r6 {
77     int a, b, c, d, e, f;
78 };
79 
ReturnR6(int n,int m)80 struct r6 ReturnR6(int n, int m)
81 {
82     struct r6 ret;
83     ret.a = n + 1;
84     ret.b = m + 1;
85     ret.c = n + 2;
86     ret.d = m + 2;
87     ret.e = n + 3;
88     ret.f = m + 3;
89     return ret;
90 }
91 
92 /* Added.  Callback function. */
93 
94 typedef int(*INT_INT_CALLBACK) (int a, int b);
95 
MakeCallback(int i,INT_INT_CALLBACK p)96 int MakeCallback(int i, INT_INT_CALLBACK p)
97 {
98     return (*p)(i, 4) + (*p)(i + 1, 5);
99 }
100 
101 
102 /* Another callback function.  This tests the various argument types. */
103 typedef double(*DBL_CALLBACK) (int a, char b, double c, float d, short e, int *f);
104 
MakeCallback2(DBL_CALLBACK p)105 double MakeCallback2(DBL_CALLBACK p)
106 {
107     int x = 1;
108     double y = p(12345, 'X', (double)1.414, (float)2.8, 44, &x);
109     return y;
110 }
111 
112 // Check that void results work for callbacks.
MakeCallback3(void (* mlcall)(int),int i)113 void MakeCallback3(void(*mlcall)(int), int i)
114 {
115     mlcall(i + 1);
116 }
117 
118 /* Test for finalisation. */
AllocateIt()119 void *AllocateIt()
120 {
121     void *p = malloc(1);
122     printf("Allocated object at %p\n", p);
123     fflush(stdout);
124     return p;
125 }
126 
FreeIt(void * p)127 void FreeIt(void *p)
128 {
129     printf("Freed object at %p\n", p);
130     fflush(stdout);
131     free(p);
132 }
133 
134 /* Test for call-by-reference.  Added in updated FFI. */
UpdateArg(int i,int * p)135 void UpdateArg(int i, int *p)
136 {
137     *p += i;
138 }
139 
140 /* Test for returning a function.  Added in updated FFI. */
acallBack(int q)141 static int acallBack(int q)
142 {
143     return q * 2;
144 }
145 
146 typedef int(*CB)(int);
147 
ReturnFn(CB * v)148 void ReturnFn(CB *v)
149 {
150     *v = acallBack;
151 }
152