SML# - Tutorial/012.3 Diff

  • Added parts are displayed like this.
  • Deleted parts are displayed like this.

[ [[トップ |Tutorial]]| [[目次|Tutorial/000]] | [[前ページ|Tutorial/012.2]] | [[ 次ページ |Tutorial/012.4]] ]
----
[[演習1|Tutorial/012]]を実際にやってみると実感するであろうが,Cでは,関
数を定義した後,その関数を呼び出すためにmain関数を書きその中に関数の呼
び出しと結果をプリントするのコードを書き,関数の定義とともにファイルに
格納し一緒にコンパイルして実行しなければならない.
これに対してMLでは,定義した関数を対話型間環境から直接種々の値に対して
呼び出してテストすることができる.これは,関数型言語の大きな利点の一つ
である.

Cの関数も,MLのように対話型環境から呼び出してテストできると便利である.
SML#のCプログラムとの連携機能を使えば,簡単に実現することができる.
この機能は,型とコンパイルに関する先端理論を駆使して実現された機能であ
るが,利用はいたって簡単である.
今回は,SML#が提供するこの先端機能を学ぼう.

!C関数を動的リンクライブラリとしてコンパイル

Cの関数をSML#の対話型環境から呼び出すには,呼び出したい関数をファ
イルに書き,それを動的リンクライブラリとしてコンパイルする.
[[Cの関数定義|Tutorial/007]]で最初に定義したCのfactorial関数を例に説明する.

まず,factorial関数を含むファイルfact.cをいつもと通りCのソースを置くフォルダに作成する.
C:\SMLSharpAndC\c>type fact.c
type fact.c
int factorial (int x) {
   int s = 1;
   while (x > 0) {
     s = x * s;
     x = x - 1;
   }
   return (s);
}

C:\SMLSharpAndC\c>
次に,このファイルを動的リンクライブラリとしてコンパイルし結果を
SML#が使用する動的リンクライブラリのためのフォルダに書き出す.
以下のコマンドを実行するだけでよい.
C:\SMLSharpAndC\c>gcc -shared -o ../dllLib fact.c
ここで,gccコンパイラに新たに与えたスイッチの意味は以下の通りである.
* '''-shared'''は動的リンクライブラリとしてコンパイルする指示
* '''-o ../dllLib/fact.dll'''は作成する動的リンクライブラリのパスの指定である.パスの中の'''..'''は一つ上のフォルダを指す.現在のフォルダがC:\SMLSharpAndC\cであるから,../dllLib/fact.dllは'''C:\SMLSharpAndC\dllLib'''を意味する.

動的リンクライブラリのためのフォルダは,[[作業用フォルダの作成と環境設定|Tutorial/004]]で作成し
環境変数によってSML#コンパイラに通知済のはずである.

実際にライブラリが作られたかを確認してみよう.
C:\SMLSharpAndC\c>gcc -shared -o ../dllLib/fact.dll fact.c
gcc -shared -o ../dllLib/fact.dll fact.c

C:\SMLSharpAndC\c>cd ../dllLib
cd ../dllLib

C:\SMLSharpAndC\dllLib>dir
dir
  ドライブ C のボリューム ラベルは XXXX です
  ボリューム シリアル番号は YYYY です

  C:\SMLSharpAndC\dllLib のディレクトリ

2007/08/04  17:24    <DIR>          .
2007/08/04  17:24    <DIR>          ..
2007/08/04  17:24            12,978 fact.dll
                1 個のファイル              12,978 バイト
                2 個のディレクトリ  21,852,004,352 バイトの空き領域

C:\SMLSharpAndC\dllLib>

!SML#から動的リンクライブラリの呼び出し

動的リンクライブラリの関数をSML#から利用するには,以下の2つを実行すればよい.
# DynamicLink.dlopen関数を用いて動的リンクライブラリのオープン.DynamicLink.dlopen関数の引数は動的リンクライブラリを表す文字列である.動的リンクライブラリを格納するフォルダがシステムのPATH変数として設定済であれば,ライブラリ名のみでよい.
# DynamicLink.dlsymと_import特殊構文を使って関数をインポート.DynamicLink.dlsymの引数は,DynamicLink.dlopenが返すライブラリハンドルと関数名の文字列である._import特殊構文は,DynamicLink.dlsymが取り出したCの関数ポインタをMLの関数に変換する処理を行う.この構文は以下のように指定する.
dlsym式 _import (引数1の型,...,引数Nの型) -> 結果の型

以下は,fact.dllのfactorial関数をインポートするコードである.
val libHandle = DynamicLink.dlopen "fact.dll";
val fact = DynamicLink.dlsym(libHandle, "factorial") : _import (int) -> int
smlのソースディレクトリに移動してこのコードを実行すると,
以下のようにfactがSML#の関数として使用可能になる.
C:\SMLSharpAndC\dllLib>cd ../sml
cd ../sml

C:\SMLSharpAndC\sml>smlsharp
smlsharp
SML# 0.30 (2007-07-03 16:16:12 JST)
# val libHandle = DynamicLink.dlopen "fact.dll";
val libHandle = 0x10000000 : unit ptr
# val fact = DynamicLink.dlsym(libHandle, "factorial")
>             : _import (int) -> int;
val fact = fn : int  -> int
#
これ以降,factを通常のMLの関数と同様に使用することができる.
# fact 1;
val it = 1 : int
# fact 2;
val it = 2 : int
# fact 3;
val it = 6 : int
# fact 4;
val it = 24 : int
# fact 10 + 10;
val it = 3628810 : int
#

!対話型環境からC関数をテストする.

以上の機能を使えば,Cの関数を対話型から簡単にテストすることができる.
その標準の手順を作っておくと,CでもMLと同様の気軽さで種々の関数を定義
し,システムを構築していくことができる.

----
[ [[トップ |Tutorial]]| [[目次|Tutorial/000]] | [[前ページ|Tutorial/012.2]] | [[ 次ページ |Tutorial/012.4]] ]