Библиотека OCaml as C, пример Hello World - PullRequest
0 голосов
/ 24 апреля 2020

I sh для вызова кода OCaml через C ++ путем компиляции OCaml в stati c или разделяемую библиотеку, которая содержит интерфейс C. Эта страница , кажется, объясняет, как создать C интерфейс для OCaml. Но как мне это сделать и скомпилировать? И как мне получить файл .h для загрузки в мой код C ++?

Кроме того, кто-то может объяснить эту часть:

Система времени выполнения OCaml состоит из трех основных частей: интерпретатор байт-кода, менеджер памяти и набор C функций, которые реализуют примитивные операции. Для вызова этих C функций предусмотрены некоторые инструкции байт-кода, обозначенные их смещением в таблице функций (таблица примитивов).

I-й OCaml может быть скомпилирован на родном машинном языке. Почему он компилируется в байт-код и интерпретируется во время выполнения? Это всегда так или только для библиотек OCaml, скомпилированных с C интерфейсом?

1 Ответ

2 голосов
/ 24 апреля 2020

Большая часть этой страницы описывает, как позвонить C из OCaml. Вы хотите сделать обратное, что описано в Расширенные темы: обратные вызовы от C до OCaml , ближе к нижней части страницы.

Когда вы делаете собственную компиляцию, нет задействован байт-код, как вы говорите. Собственный компилятор (ocamlopt) создает файлы обычных объектов (.o в Unix) и дополнительные файлы, содержащие метаданные OCaml.

Если вы посмотрите на Расширенный пример с обратными вызовами , вы увидите пример, где основная программа находится в C, с вызовами двух функций, определенных в OCaml. Вещи должны работать аналогично в C ++. (Я сделал это только в C, однако.)

Обновление

Вот отработанный пример с использованием кода из Расширенный пример с обратными вызовами . Я запускаю этот код в Ubuntu 18.04.4 (x86_64).

Код 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

Скомпилируйте этот код и запросите полный объектный файл:

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

Переименуйте код C в modwrap. cc. (Код приведен в разделе руководства OCaml.)

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

int fib(int n)

Обратите внимание, что включаемые файлы OCaml обусловлены тем, включены ли они из C или C ++ (как и почти все заголовочные файлы). в эти дни).

Основная функция из раздела руководства OCaml также допустима C ++; переименуйте его в 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)

Теперь скомпилируйте и скомпонуйте все:

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

Теперь запустите программу

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

Нет автоматов c генерация заголовочных файлов. В этом примере extern строк main.cc по сути являются заголовочными файлами. Если вам нужен заголовочный файл, вам придется написать что-то вроде этого самостоятельно.

Обновление 2

Вот команды для создания фактической библиотеки stati c содержащий функции OCaml и их оболочки. Это предполагает, что вы выполнили приведенные выше компиляции для создания bigmod.o и modwrap.o:

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

Теперь вы можете использовать эту библиотеку в своем коде C ++ (представленном main. cc):

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

Обновление 3

(я обновил вышеупомянутые команды для работы в Unbuntu.)

...