简体   繁体   English

OCaml 作为 C 库,hello world 示例

[英]OCaml as C library, hello world example

I wish to call OCaml code through C++ by compiling OCaml to a static or shared library that contains a C interface.我希望通过 C++ 调用 OCaml 代码,方法是将 OCaml 编译为 static 或包含 C 接口的共享库。 This page seems to explain how to create a C interface for OCaml.这个页面似乎解释了如何为 OCaml 创建一个 C 接口。 But how do I do it and compile it?但是我该怎么做和编译呢? And how do I obtain the.h file to load in my C++ code?以及如何获取要加载到我的 C++ 代码中的 .h 文件?

Also, could someone explain to be this part:此外,有人可以解释为这部分:

The OCaml runtime system comprises three main parts: the bytecode interpreter, the memory manager, and a set of C functions that implement the primitive operations. OCaml 运行时系统包括三个主要部分:字节码解释器、memory 管理器和一组实现原始操作的 C 函数。 Some bytecode instructions are provided to call these C functions, designated by their offset in a table of functions (the table of primitives).提供了一些字节码指令来调用这些 C 函数,这些函数由函数表(原语表)中的偏移量指定。

I thougth OCaml could be compiled to native machine language.我认为 OCaml 可以编译为本地机器语言。 Why it is compiled to bytecode and interpreted at runtime?为什么它被编译成字节码并在运行时解释? Is it always like that, or only for OCaml libraries compiled with C interface?总是这样,还是只针对使用 C 接口编译的 OCaml 库?

Most of that page describes how to call C from OCaml.该页面的大部分内容描述了如何从 OCaml 调用 C。 You want to do the reverse, which is described in Advanced Topics: callbacks from C to OCaml , closer to the bottom of the page.您想要执行相反的操作,如高级主题中所述:从 C 到 OCaml 的回调,更靠近页面底部。

When you do native compilation there is no bytecode involved, just as you say.正如您所说,当您进行本机编译时,不涉及字节码。 The native compiler (ocamlopt) produces ordinary object (.o in Unix) files and extra files containing OCaml metadata.本机编译器 (ocamlopt) 生成普通的 object(Unix 中的 .o)文件和包含 OCaml 元数据的额外文件。

If you look at Advanced Example with callbacks , you'll see an example where the main program is in C, with calls to two functions defined in OCaml.如果您查看带有回调的高级示例,您会看到一个示例,其中主程序位于 C 中,并调用了 OCaml 中定义的两个函数。 Things should work similarly in C++. C++ 中的工作应该类似。 (I have only done this in C myself, however.) (不过,我自己只在 C 中这样做过。)

Update更新

Here is the worked-out example using the code from Advanced example with callbacks .这是使用带有回调的高级示例中的代码的解决示例。 I am running this code on Ubuntu 18.04.4 (x86_64).我在 Ubuntu 18.04.4 (x86_64) 上运行此代码。

The OCaml code looks like this: OCaml 代码如下所示:

$ cat mod.ml
let rec fib n = if n < 2 then 1 else fib (n - 1) + fib (n - 1)

let format_result n = Printf.sprintf "Result is: %d\n" n

let () = Callback.register "fib" fib
let () = Callback.register "format_result" format_result

Compile this code and ask for a complete object file:编译此代码并要求提供完整的 object 文件:

$ ocamlopt -output-obj -o bigmod.o mod.ml

Rename the C code to modwrap.cc.将 C 代码重命名为 modwrap.cc。 (The code is given in the OCaml manual section.) (代码在 OCaml 手册部分给出。)

$ head -6 modwrap.cc
#include <stdio.h>
#include <string.h>
#include <caml/mlvalues.h>
#include <caml/callback.h>

int fib(int n)

Note that the OCaml include files are conditionalized as to whether they're being included from C or C++ (as are almost all header files these days).请注意,OCaml 包含文件取决于它们是否包含在 C 或 C++ 中(这些天几乎所有 header 文件都是如此)。

The main function from the OCaml manual section is also valid C++; OCaml 手册部分的主要 function 也是有效的 C++; rename it to main.cc:将其重命名为 main.cc:

$ head -7 main.cc
#include <stdio.h>
#include <caml/callback.h>

extern int fib(int n);
extern char * format_result(int n);

int main(int argc, char ** argv)

Now compile and link everything:现在编译并链接所有内容:

$ g++ -c modwrap.cc
$ g++ -o myprog -I $(ocamlopt -where) \
    main.cc modwrap.o bigmod.o $(ocamlopt -where)/libasmrun.a -ldl
$

Now run the program现在运行程序

$ ./myprog
fib(10) = Result is: 89

There is no automatic generation of header files.没有自动生成 header 文件。 In this example the extern lines of main.cc are the header file in essence.在本例中, main.ccextern行本质上是 header 文件。 If you want a header file you'll have to write something like this yourself.如果你想要一个 header 文件,你必须自己写这样的东西。

Update 2更新 2

Here are the commands for creating an actual static library containing the OCaml functions and their wrappers.以下是用于创建包含 OCaml 函数及其包装器的实际 static 库的命令。 This assumes that you have done the compiles above to create bigmod.o and modwrap.o:这假设您已完成上述编译以创建 bigmod.o 和 modwrap.o:

$ cp $(ocamlopt -where)/libasmrun.a libmyoc.a
$ ar r libmyoc.a bigmod.o modwrap.o

Now you can use this library in your C++ code (represented by main.cc):现在您可以在 C++ 代码(由 main.cc 表示)中使用此库:

$ g++ -o myprog -I $(ocamlopt -where) main.cc -L . -lmyoc -ldl
$ ./myprog
fib(10) = Result is: 89

Update 3更新 3

(I updated the above commands to work on Unbuntu.) (我更新了上述命令以在 Unbuntu 上工作。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM