C functions with structs

In addition to integers and doubles, you can pass a tuple as a struct data to C. A care must be taken, however, since data alignment in C struct is implementation dependent. To deal with this problem, the cureent SML# 0.20 release adotp the following most strict policy on data alignment in tuple.

  • a real data is on 8 byte boundary (padding is inserted if needed)
  • an int data is on 4 byte boundary
  • a packed data of less than 1 word (such as char) is not supported

Any tuple satisfying these alignment condition can be passed to C as a pointer to the corresponding struct data.

The following is an example C function that takes a struct pointer.

 #include <stdio.h>
 typedef struct {double x; int y;} foo;
 typedef struct {int y; int padding; double x;} bar;
 int f (foo *a)
 {
   printf ("%g\n", (*a).x);
   printf ("%d\n", (*a).y);
   return (a->y + 1);
 }
 int g (bar *a)
 {
   printf ("%g\n", a->x);
   printf ("%d\n", a->y);
   return (a->y + 1);
 }

These functions can be called from SML# as follwos.

 val a = DynamicLink.dlopen "./struct.so";
 val fName = DynamicLink.dlsym(a, "f");
 val gName = DynamicLink.dlsym(a, "g");
 val f = fName : _import (real*int) -> int;
 val g = gName : _import (int*real) -> int;
 f (3.14,99);
 g (99,3.14);

SML# prints the following result:

 # use "struct.sml";
 val a = 0x083d8550 : unit ptr
 val fName = 0x45154724 : unit ptr
 val gName = 0x45154761 : unit ptr
 val f = fn : real * int  -> int
 val g = fn : int * real  -> int
 3.14
 99
 val it = 100 : int
 3.14
 99
 val it = 100 : int
 #

In future, we plan to implement an architecture dependent configuration of alignment policy.

Last modified:2007/03/30 09:35:24
Keyword(s):
References:[Seamless Interoperability with C] [Program Examples]