nativeコードにおける動的リンク

このページは最後に更新されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

last mod. 2008-12-19 (金) 17:25:55

3.11からはnativeコードにおける動的リンクがサポートされました。動的リンクを用いるとプラグインのような機能や、実行中にコードの一部を置き換えるホットスワップなどが実現できます。

ここでは、階乗計算を行うモジュールの動的リンクを例に挙げ、ネイティブコードにおける動的リンクについて説明します。

概要

dynlink.png

動的リンクはDynlinkモジュールを使って行います。

WindowsのDLLなどとは異なり、ロードするモジュールから、ロードされるモジュールの関数や値に直接アクセスすることはできません。 そのため、ロードされるモジュールが、自分の関数や値をロードするモジュールに登録する必要があります。

今回の例では、

  1. Factモジュールはロードされる
  2. Factモジュールが自分自身をFactStub?に登録する
  3. MainモジュールがFactStub?に登録された関数を呼び出す

という流れで処理を行います。

コード

factStub.ml

Factが関数を登録するためのモジュールです。 あとから値を書き換えるので、option型の参照型になっています。

let fact : (int -> int) option ref =
  ref None

fact.ml

動的リンクされるモジュールです。階乗を計算する関数を定義した後、その関数をFactStub?に登録します。

let rec fact =
  function
      0 -> 1
    | n -> n * fact (n-1)

let _ =
  FactStub.fact := Some fact

main.ml

動的リンクを行うモジュールです。Dynlink.loadfileを用いてFactモジュールをロードした後、FactStub?に登録された関数を呼び出しています。

let _  =
  try
    Dynlink.loadfile "fact.cmxs";
    match !FactStub.fact with
        Some f ->
          Printf.printf "%d\n" (f 10)
      | None ->
          failwith "load failed"
  with Dynlink.Error e ->
    print_endline (Dynlink.error_message e)

コンパイル/実行例

Factモジュールを-sharedオプションをつけてコンパイルし、動的リンク可能なプラグインを生成します。このときの拡張子は.cmxsが標準的です。

$ ocamlopt -c factStub.ml
$ ocamlopt -o fact.cmxs -shared fact.ml

Mainをコンパイルします。このときdynlink.cmxaをリンクする必要があります。

$ ocamlopt -o fact-test dynlink.cmxa factStub.ml main.ml

実行してみましょう。

$ fact-test
3628800

成功しました。

まとめ

ここでは階乗計算を行うモジュールを例として、ネイティブコードにおける動的リンクについて解説しました。動的リンクを活用することで、より柔軟なプログラムが可能になるでしょう。

新規 編集 添付