1/* Example code for a C-library accessible from ML
2using the CInterface structure.
3
4Copyright David C.J. Matthews 1999, 2009, 2015
5
6This library is free software; you can redistribute it and/or
7modify it under the terms of the GNU Lesser General Public
8License version 2.1 as published by the Free Software Foundation.
9
10This library is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13Lesser General Public License for more details.
14
15You should have received a copy of the GNU Lesser General Public
16License along with this library; if not, write to the Free Software
17Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18*/
19/*
20Linux: cc -shared -o Foreign ForeignTest.c
21Windows: cl /MT ForeignTest.c /link /dll /out:Foreign.dll /def:Foreign.def
22Mac 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. */
29char *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}
38typedef struct _tree {
39    struct _tree *left, *right;
40    int	nValue;
41} *tree;
42
43int 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. */
50struct r2 { int n, m; };
51
52struct 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/* Added.  Callback function. */
61
62typedef int(*INT_INT_CALLBACK) (int a, int b);
63
64int MakeCallback(int i, INT_INT_CALLBACK p)
65{
66    return (*p)(i, 4) + (*p)(i + 1, 5);
67}
68
69
70/* Another callback function.  This tests the various argument types. */
71typedef double(*DBL_CALLBACK) (int a, char b, double c, float d, short e, int *f);
72
73double MakeCallback2(DBL_CALLBACK p)
74{
75    int x = 1;
76    double y = p(12345, 'X', (double)1.414, (float)2.8, 44, &x);
77    return y;
78}
79
80// Check that void results work for callbacks.
81void MakeCallback3(void(*mlcall)(int), int i)
82{
83    mlcall(i + 1);
84}
85
86/* Test for finalisation. */
87void *AllocateIt()
88{
89    void *p = malloc(1);
90    printf("Allocated object at %p\n", p);
91    fflush(stdout);
92    return p;
93}
94
95void FreeIt(void *p)
96{
97    printf("Freed object at %p\n", p);
98    fflush(stdout);
99    free(p);
100}
101
102/* Test for call-by-reference.  Added in updated FFI. */
103void UpdateArg(int i, int *p)
104{
105    *p += i;
106}
107
108/* Test for returning a function.  Added in updated FFI. */
109static int acallBack(int q)
110{
111    return q * 2;
112}
113
114typedef int(*CB)(int);
115
116void ReturnFn(CB *v)
117{
118    *v = acallBack;
119}
120