Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/61.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何编译OCaml和C/C++;相互依赖的代码_C++_C_Ocaml - Fatal编程技术网

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