概要 †

  • OCaml特有の話
    • OCamlの関数を.soなり.dllなりのシンボルとして直接エクスポートすることはできない。 Cの関数でスタブを書く必要がある。
    • OCaml側で, モジュール初期化時に Callback.register 文字列 関数 とすれば 関数を "文字列" という名前でエクスポートできる
    • C側では*caml_named_value(文字列)として関数の名前を取得する。
    • caml_callbackで関数を呼ぶ
  • FFI一般の話
    • OCamlランタイムを初期化する必要がある。
    • OCamlの値とCの値の相互変換が必要である。下の例ではVal_int(C→OCaml)とInt_val(OCaml→C)を用いている。 OCamlのint型は31ビット幅であることに注意。

Linuxの場合 †

ライブラリ側ファイル †

  • foo.ml
    let succ x = x+1
    let _ = Callback.register "succ" succ
  • foostub.h
    int succ_caml(int x);
  • foostub.c
    #include <caml/mlvalues.h>
    #include <caml/callback.h>
    #include "foostub.h"
    int succ_caml(int x) {
      return Int_val(caml_callback(*caml_named_value("succ"), Val_int(x)));
    }

コンパイル &dagger;

  • ocamlcにオプション -output-obj -o libname.so とすれば共有ライブラリが得られる.
    gcc -I/usr/local/lib/ocaml -c foostub.c
    ocamlc -output-obj -o libfoo.so foo.ml foostub.o

プログラム本体 &dagger;

  • usefoo.c
    #include "foostub.h"
    #include <stdio.h>
    #include <caml/callback.h>
    
    int main(int argc, char** argv) {
      caml_startup(argv);
      printf("%d\n", succ_caml(10));
      return 0;
    }

コンパイル &dagger;

  • 普通の共有ライブラリとしてリンクして実行。
    gcc -I/usr/local/lib/ocaml -o usefoo libfoo.so usefoo.c

実行 &dagger;

$ export LD_LIBRARY_PATH=`pwd`:$LD_LIBRARY_PATH
$ ./usefoo
11

ネイティブコードの場合 &dagger;

  • 上のocamlcをocamloptに変えるだけ

(参考)静的リンクの場合 &dagger;

  • -output-obj foo.o で オブジェクトコードを生成できるのでarで.aを作るなりリンクするなりすればよい
    • その場合 -lcamlrun (ネイティブコードなら -lasmrun) を付けるのを忘れずに
    • 以下はネイティブコード用静的リンク
      ocamlopt -output-obj -o foo.o foo.ml
      gcc -I/opt/local/lib/ocaml -c foostub.c 
      gcc -I/opt/local/lib/ocaml -c usefoo.c
      gcc -o usefoo foo.o foostub.o usefoo.o -L/opt/local/lib/ocaml -lasmrun

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2011-01-01 (土) 19:52:10 (3583d)