§ 6.3. Multiple argument functions and structs
In using C functions that takes multiple arguments or struct, the programmer should aware the following points.
-
Multiple argument functions
C functions in general take multiple arguments. For example,libm library contains the following function to compute power.double pow(double x, double y);
pow takes two parameters of type double and returns a value of type double. In SML#, this is declared by listing the argument types in parenthesis like C as follows.
val C_pow = _import "pow" : (real, real) -> real
Since the current version of SML# does not provide user defined multiple argument functions, SML# compiler converts this function to a function that takes a tuple of values. For the above declaration, SML# generates the following binding.
val C_pow = _ : real * real -> real
After this declaration, C_pow is used as a function to takes a pair as shown in the following.
# val C_pow = _import "pow" : (real, real) -> real;
val C_pow = _ : real * real -> real
# val x = C_pow (2.0,3.0);
val x = 8.0 : real
# map C_pow [(1.0,2.0), (2.0,3.0), (3.0,4.0)];
val it = [1.0, 8.0, 81.0] : real list -
Struct argument
As show in Table 6.1, a pointer to a struct in C corresponds to a record in SML#. For example,a C functionstruct S double x; double y;;
int f(struct S* s);can be imported as:
val f = _import : (real * real) -> int;
This declaration yields the following binding.
val f = _ : real * real -> real
In this case, a record generated in SML# is directly passed to the C function. Since a record in SML# has the same memory layout as the corresponding struct in C, the passed record can be directly accessed by the C code. However, it should be noted that C is an imperative language that can mutate any memory contents. If C code mutates a record, then the original SML# record is mutated. Figure 6.2 show a simple example of passing a record to C.
samle.c file:
struct S {double X; double Y;};
int f(struct S* s) {
s->X = 2.0;
return(s->X * s->Y);
}sample.sml file:
val f = _import "f" : real * real -> real
val x = (1.1, 2.2);
val y = f x;
print ("The value of y:" R̂eal.toString y "̂\n");
print ("The value of the first x:" R̂eal.toString (#1 x) "̂\n");Execution:
# gcc -c sample.c
# smlsharp sample.sml sample.o
# a.out
The value of y:4.4
The value of the first x:2.0Figure 6.2. Passing a tuple to C function