準備
ctypesパッケージが必要
opamでインストールできる。$ opam install ctypes
libffiが必要
$ dpkg --list | grep libffiii libffi-dev:i38 3.0.10-3 i386 Foreign Function Interface library
ii libffi5:i386 3.0.10-3 i386 Foreign Function Interface library
私のシステム(Debian Wheezy)にはもうインストールされていた。
ソース
hello.h
void print_hello(void);hello.c
#include <stdio.h>#include "hello.h"
void print_hello(void) {
printf("hello, world!\n");
}
hello.ml
open Ctypesopen Foreign
let print_hello =
foreign "print_hello" (void @-> returning void)
hello.mli
val print_hello : unit -> unitmain.ml
open Hellolet () =
print_hello ();
コンパイル
共有ライブラリの作成
$ gcc -c -fPIC -Wall hello.c$ gcc -shared -o libhello.so hello.o
OCamlソースのコンパイル
$ ocamlfind ocamlopt -linkpkg hello.mli$ ocamlfind ocamlopt -linkpkg -package ctypes,ctypes.foreign hello.ml
$ ocamlfind ocamlopt -cclib libhello.so -linkpkg -g -thread -package ctypes.foreign -package core -o main hello.cmx
実行
$ LD_LIBRARY_PATH=. ./mainhello, world!
動いた!
まとめ
簡単そうだったけど、試行錯誤したので、メモを残しておこう。静的ライブラリは使えない(使えなかった)
最初は静的ライブラリが使えると思っていた。いろいろ試していたのだけど、
Fatal error: exception Dl.DL_error("〜/main.native: undefined symbol: print_hello")
というエラーメッセージを見て、動的ライブラリでないと駄目だということに気が付いた。
リンカへのライブラリ指定
hello.cを置いたディレクトリの下に、ocamlソース用のディレクトリを作成して、corebuildコマンドでビルドしていた。$ corebuild -pkg ctypes.foreign -lflags -cclib,-L../..,-cclib,libhello.so main.native
実行すると、
$ ./main.native
main.native: error while loading shared libraries: ../../libhello.so: cannot open shared object file: No such file or directory
となってしまい、../../libhello.soを参照してしまう。
カレントディレクトリにlibhello.soを置いて、corebuildを実行してみたが、余計なファイルがあると、以下のようなエラーが発生し、ビルドできない。
$ corebuild -pkg ctypes.foreign -lflags -cclib,libhello.so main.native
SANITIZE: a total of 1 file that should probably not be in your source tree
has been found. A script shell file
"/home/satoshi/workspace/real_world_ocaml/ffi/ocaml/_build/sanitize.sh" is
being created. Check this script and run it to remove unwanted files or use
other options (such as defining hygiene exceptions or using the -no-hygiene
option).
IMPORTANT: I cannot work with leftover compiled files.
ERROR: Leftover object files:
File libhello.so in . has suffix .so
Exiting due to hygiene violations.
あきらめて、ビルドにはocamlfindコマンドを使うことにした。
シグネチャの作成
corebuildを使って、以下のようなコマンドを実行すると、mlファイルからシグネチャを作ることができる。$ corebuild -pkg ctypes.foreign hello.inferred.mli
モジュールの公開メソッドが多いとき、自分で一から書くよりは楽ちん。
0 件のコメント:
コメントを投稿