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