我正在尝试包装C代码以将其与OCaml链接。
让代码可以正常编译,但是链接不起作用。
我的ML测试代码:
external deal: int * int -> bool = "caml_deal"
let (bool) =
deal(1, 1)
我也有一个存根:
#include <stdio.h>
#define CAML_NAME_SPACE
#include <caml/mlvalues.h>
#include <caml/memory.h>
#include "clang_deal.h"
CAMLprim value
caml_deal(value ml_tuple)
{
CAMLparam1( ml_tuple );
int players = Int_val(Field(ml_tuple, 0));
int treshold = Int_val(Field(ml_tuple, 1));
int res = deal(players, treshold);
return Val_bool(players);
}
我的交易定义为:
#include "utils.h"
int deal(int players, int treshold) {
dealer d{};
return d.deal(players, treshold);
};
我能够很好地编译代码。喜欢:
$ ocamlc -c test_stubs.c
$ gcc -c clang_deal.cpp -std=c++17 -I./pbc/include
$ ocamlc -c test.ml
当我尝试链接时,它会引发错误:
$ ocamlc -o dealer test.cmo test_stubs.o clang_deal.o
File "_none_", line 1:
Error: Error while linking test.cmo:
The external function `caml_deal' is not available
nm(1)
显示caml_deal
是在文本段中定义的。
$ nm test_stubs.o
0000000000000000 T _caml_deal
U _caml_local_roots
U _deal
有什么建议吗?
答案 0 :(得分:2)
通常,您必须按“拓扑”顺序列出模块。即,您需要在使用该模块的其他模块之前列出该模块。我会测试一下是否可以解决您的问题。
更新
仔细观察,我会发现一些问题,或者至少是我不希望的事情。
您的存根代码是用C编写的,但它调用了用C ++编写的函数。 C ++是专门为能够调用C函数而设计的,但是据我所知,通常情况并非如此。
您的最终编译使用ocamlc
来产生字节码。我认为您无法轻松地将字节码与任意外部本机代码链接。如果生成的不是您想要的“自定义”字节码解释器,则可以这样做。
如果我将代码更改为全部C,如果将一些顶级代码添加到test.ml,并且如果我使用ocamlopt
进行最终的编译和链接,则对我来说工作如下。 / p>
$ cat clang_deal.c
int deal (int players, int threshold)
{
return !!(players + threshold);
}
$ cat test.ml
external deal: int * int -> bool = "caml_deal"
let (bool) = deal (1, 1)
let main () = Printf.printf "%b\n" bool
let () = main ()
$ ocamlopt -o deal clang_deal.c test_stubs.c test.ml
$ ./deal
true
这似乎不完全是您想要做的,但是也许它可以使您克服第一个或两个问题。
作为附带说明,尚不清楚您是否意识到bool
只是test.ml
中的普通变量名称。不需要将其放在括号中,并且不会更改含义(例如,与类型名称相对应)。
答案 1 :(得分:0)
感谢您的所有帮助。我找出了问题所在。
我的导出函数caml_deal()已定义,因此文本段中有_caml_deal
。但是,我无法链接依赖C ++代码的库之一(是的,我的头中有extern "C"
)。事实证明,如果C / C ++代码缺少一个或多个符号,ocamlopt
将该问题报告为顶级功能不可用。从某种意义上说,这甚至是有意义的。但是,对于像我这样的新手,更详细的错误将更具有洞察力。