C++ 如何编译OCaml和C/C++;相互依赖的代码
我在定义接受C++ 如何编译OCaml和C/C++;相互依赖的代码,c++,c,ocaml,C++,C,Ocaml,我在定义接受uint64\t和char*的C void函数的签名时遇到问题。我试过int64->string-> 我也不知道如何将我的C++文件(C语言接口)一起编译< /p> events.ml open Lwt.Infix external call: int64 -> string -> _ = "function_pointer_caller" let begin_event pointer = Lwt_unix.sleep 5.0 >>= fun
uint64\t
和char*
的C void函数的签名时遇到问题。我试过int64->string->
<>我也不知道如何将我的C++文件(C语言接口)一起编译< /p>
events.ml
open Lwt.Infix
external call: int64 -> string -> _ = "function_pointer_caller"
let begin_event pointer =
Lwt_unix.sleep 5.0 >>= fun () ->
call pointer "message"
let () = Callback.register "begin_event" begin_event
接口.c:
#include <stdio.h>
#include <string.h>
#include <caml/mlvalues.h>
#include <caml/callback.h>
#include <caml/alloc.h>
#include <caml/bigarray.h>
extern void register_function_callback();
void print_from_event(char* message) {
printf("OCaml event: %s\n", message);
}
void function_pointer_caller(uint64_t pointer, char* message)
{
void (*f)(char *);
f = pointer;
}
void register_function_callback() {
static const value *begin_event_closure = NULL;
if (begin_event_closure == NULL)
{
begin_event_closure = caml_named_value("begin_event");
if (begin_event_closure == NULL)
{
printf("couldn't find OCaml function\n");
exit(1);
}
}
uint64_t pointer = (uint64_t) &function_pointer_caller;
caml_callback(*begin_event_closure, (int64_t) &pointer);
}
第一个命令编译正常,但g++给出
event_emitter.o: In function `camlEvent_emitter__begin_event_90':
:(.text+0x3f): undefined reference to `camlLwt_unix__sleep_695'
:(.text+0x4c): undefined reference to `camlLwt__bind_1276'
collect2: error: ld returned 1 exit status
请注意,我从上一个命令(ocamlopt
)中插入了interface.o
,并在g++中链接,因为ocamlopt
实际上将C文件传递给C编译器
我不知道为什么它会抱怨
Lwt\uunix
的事情,因为我已经在ocamlopt
中用它们编译了 对于“警告”消息,您应该更加小心,不要依赖于将构建过程绑定到配置的东西。请避免使用根控制台
[WARNING] Running as root is not recommended
在根环境中,库的路径可能很复杂
根据您的pastebin,我看到链接器无法找到lwt_unix_存根库。请不要把“.a”和“.so”库混在一起(/root/.opam/4.10.0/lib/lwt/unix/liblwt\u unix\u stubs.a/root/.opam/4.10.0/lib/stublibs/dlllwt\u unix\u stubs.so
)!”。'表示静态生成,而'.so'表示动态生成
适用于我的构建示例(Ubuntu Linux,ocaml 4.05.0):
使用$(ocamlopt-where)/libasmrun.a
是个坏主意。使用-run和-L作为库的路径更迂腐
如果您对某些未定义的符号有问题,最好使用readelf查找缺少的库。您应该更小心地处理“警告”消息,而不要依赖于将构建过程绑定到配置的东西。请避免使用根控制台
[WARNING] Running as root is not recommended
在根环境中,库的路径可能很复杂
根据您的pastebin,我看到链接器无法找到lwt_unix_存根库。请不要把“.a”和“.so”库混在一起(/root/.opam/4.10.0/lib/lwt/unix/liblwt\u unix\u stubs.a/root/.opam/4.10.0/lib/stublibs/dlllwt\u unix\u stubs.so
)!”。'表示静态生成,而'.so'表示动态生成
适用于我的构建示例(Ubuntu Linux,ocaml 4.05.0):
使用$(ocamlopt-where)/libasmrun.a
是个坏主意。使用-run和-L作为库的路径更迂腐
如果您对一些未定义的符号有问题,最好使用readelf找出缺少的库。ocamlopt实用程序不仅仅是链接指定的编译单元和库,它还嵌入了架构启动代码,它不包括在
asmrun
库中。使用-output obj
可以获得这段代码,但我发现它有点容易出错,而且很难维护,因为它不是真正可组合的1
因此,最好依靠ocamlopt来构建最终的二进制文件,它将由用不同语言编写的模块组成。每个单元都将使用适合其编写语言的工具构建。让我们构建events.ml
编译单元:
ocamlfind ocamlopt -c -package lwt.unix events.ml
现在,让我们构建接口(我们可以在这里使用cc
,但是使用ocamlopt将为我们节省一些提供包含位置的麻烦)
现在,让我们构建C++部分(但是首先修复它,使用<代码> CAMLYMIGE/<代码>代替<代码> CAMLYPROSTOR> <代码>,因为我们需要本地运行时)。 现在,当我们拥有所有的单位时,我们已经准备好执行最后的链接命令:
ocamlfind ocamlopt events.cmx interface.o main.o -package lwt.unix -package lwt -thread -linkpkg -o emitter
等等,我们可以用/emitter
运行我们的程序
1) 对多个编译单元使用此选项很容易导致符号冲突 ocamlopt实用程序不仅仅是链接指定的编译单元和库,它还嵌入了体系结构启动代码,该代码不包括在
asmrun
库中。使用-output obj
可以获得这段代码,但我发现它有点容易出错,而且很难维护,因为它不是真正可组合的1
因此,最好依靠ocamlopt来构建最终的二进制文件,它将由用不同语言编写的模块组成。每个单元都将使用适合其编写语言的工具构建。让我们构建events.ml
编译单元:
ocamlfind ocamlopt -c -package lwt.unix events.ml
现在,让我们构建接口(我们可以在这里使用cc
,但是使用ocamlopt将为我们节省一些提供包含位置的麻烦)
现在,让我们构建C++部分(但是首先修复它,使用<代码> CAMLYMIGE/<代码>代替<代码> CAMLYPROSTOR> <代码>,因为我们需要本地运行时)。 现在,当我们拥有所有的单位时,我们已经准备好执行最后的链接命令:
ocamlfind ocamlopt events.cmx interface.o main.o -package lwt.unix -package lwt -thread -linkpkg -o emitter
等等,我们可以用/emitter
运行我们的程序
1) 对多个编译单元使用此选项很容易导致符号冲突 尝试
extern“C”
@KamilCuk,但是仍然需要指定哪个.cc文件将与.ml一起编译,否则在构建时它将始终导致与ocaml的“未定义引用”链接<代码>我已经在ocamlopt中编译了它们不$(ocamlopt-where)/libasmrun.a
do-lasmrun
。和-lunix
@KamilCuk对不起,我不明白<代码>$(ocamlopt-where)/libasmrun.a与-lasmrun
相同,不是吗?和-lunix
给出/usr/bin/ld:找不到-lunix
:/导航到ocmlopt-where
,列出库中的符号并查找缺少的符号。我在$(ocamlopt-where)/*中的部分内容;do nm-gD“$i”| grep camlwt_unix_____sleep_695&&echo$i;完成
不是吗?
-我想如果链接器找到相同的库也是一样的。
g++ -c main.cc -o main.o -I `ocamlc -where`
ocamlfind ocamlopt events.cmx interface.o main.o -package lwt.unix -package lwt -thread -linkpkg -o emitter