Is it possible to check at runtime for badly-behaved native functions in OCaml? This would be useful in mixed C/OCaml projects.
When implementing an intrinsic OCaml function in C, care has to be taken to live in harmony with the runtime.
For instance, in the following example add
in libadd
intentionally does not use CAMLreturn
as would be appropriate.
(* foo.ml *)
external add : int -> int -> int = "add";;
Printf.printf "%d\n" (add 4 5);;
and the C source file
// libadd.c
#include <caml/memory.h>
#include <caml/mlvalues.h>
CAMLprim value
add(value ml_x, value ml_y)
{
CAMLparam2(ml_x, ml_y);
long x = Long_val(ml_x);
long y = Long_val(ml_y);
// intentional mistake here
// don't use CAMLreturn
return Val_long(x + y);
}
If you compile this code using either OCaml compiler
$ ocamlopt foo.ml libadd.c
$ ocamlc -custom foo.ml libadd.c
Then a.out
just prints 9
without complaint.
./a.out
9
Is there a way to get either compiler to emit additional checks around native function calls to check that the OCaml calling convention has been adhered to?
ocaml does nothing wrt to this issue, the error relies in the C code that is compiled by gcc. And gcc cannot check that the return is compatible or not with Ocaml.
May be one way to limit mis-written C for Ocaml is to redefine return
to avoid using it :
#define return _forbidden_
Your initial C code will fail to compile if you include those define in your code.
It does not solve the issue, but it may be useful to force the user to take care of the way the function shall return.
Another way is having a sanity script checking that any function whose return type is CAML*
does not contain any return
...
The CAML macros are just simple preprocessor macros. You can always just write the underlying C code directly instead of using the macro. Nothing short of changing gcc to know about how to interface with ocaml will fix that.
There is one simple trick for matching BEGIN and END style macros though to fail if one of the two is forgotten accidentally. The trick is to have an opening { in the BEGIN macro and a closing } on the END macro. Forgetting one of them will give an error because then {} don't balance.
Problem is that a function can have multiple return statements making the use of unbalanced {} impossible.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With