OCaml动态检查行为不当的本机功能

时间:2018-06-03 04:05:54

标签: c ocaml

是否可以在运行时检查OCaml中性能不佳的本机功能?这在混合C / OCaml项目中很有用。

在C中实现内在的OCaml函数时,必须注意与运行时协调一致。

例如,在以下示例中,add中的libadd故意不使用CAMLreturn

(* foo.ml *)
external add : int -> int -> int = "add";;

Printf.printf "%d\n" (add 4 5);;

和C源文件

// 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);
}

如果使用OCaml编译器

编译此代码
$ ocamlopt foo.ml libadd.c
$ ocamlc -custom foo.ml libadd.c

然后a.out只会打印9而无需投诉。

./a.out
9

有没有办法让编译器在本机函数调用周围发出额外的检查来检查是否已遵守OCaml调用约定?

2 个答案:

答案 0 :(得分:5)

ocaml对此问题没有任何意义,错误依赖于由gcc编译的C代码。并且gcc无法检查返回是否与Ocaml兼容。

可能是限制错误写入C的一种方法,即Ocaml重新定义return以避免使用它:

#define return _forbidden_

如果在代码中包含那些定义,那么您的初始C代码将无法编译。

它没有解决问题,但强制用户注意函数返回的方式可能很有用。

另一种方法是让一个健全性脚本检查返回类型为CAML*的任何函数都不包含任何return ...

答案 1 :(得分:1)

CAML宏只是简单的预处理器宏。您始终可以直接编写底层C代码而不是使用宏。没有什么能够改变gcc知道如何与ocaml接口将解决这个问题。

有一个简单的技巧可以匹配BEGIN和END样式的宏,但如果两个中的一个被意外忘记就会失败。诀窍是在END宏上有一个开口{在BEGIN宏和一个闭合}。忘记其中一个会产生错误,因为{}没有平衡。

问题是函数可能有多个返回语句,使得不可能使用不平衡{}。