SML# - Tutorial/012.4 Diff

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

[ [[トップ |Tutorial]]| [[目次|Tutorial/000]] | [[前ページ|Tutorial/012.3]] | [[ 次ページ |Tutorial/013]] ]
----
SML#からCの種々の関数を呼び出すステップは
# Cの関数のファイルtemp.cを作成する.
# gcc -shared -o ../lddLib/temp.dll temp.c
# temp.cの関数を呼び出すSMLソースファイルを作成する.
である.この3番目の標準手順を覚えておくと,Cの関数をMLと同様の気軽
さでSML#の対話型環境から呼び出しテストすることができる.
[[演習1|Tutorial/012.1]]の問1と問3で作成したの8つの関数
# power
# shou
# amari
# sigmaN
# sigmaN2
# A
# B
# C
# fib
を例に,その手順を学ぼう.以下,これら関数を含むファイルをex1.cとする.

!SML#インタフェースファイルテンプレートの作成
Cの関数のインタフェイスファイルを作成する情報は,C関数にすべて含まれ
ているので,Cの関数ファイルex1.cを
[[作業用フォルダの作成と環境設定|Tutorial/004]]で作成した
SML#のライブラリフォルダに
ex1.smlとしてコピーする.

!関数ヘッダーの抜き出し
ex1.sml内容はCのコードである.これをSML#のインターフェイスコードに
変換するために,Cの関数定義のヘッダ行以外をすべて消去する.本例の場
合,以下のような内容となる.
int power(int n, int k) {
int shou(int x, int y) {
int amari(int x, int y) {
int sigmaN(int k, int n) {
int sigmaN2(int k, int n) {
int A(int a, int b, int n) {
int B(int a, int b, int n) {
int C(int a, int b, int c, int n) {
int fib (int n) {

!動的ライブラリのオープン構文の作成
ファイルの先頭に以下のコードを作成する.
val dlName = "ex1.dll";
val dllLib = DynamicLink.dlopen(dlName);
fun bind fName = DynamicLinc.dlsym(dllLib,fname);
関数bindは,ライブラリから指定された関数名のポインタを取り出す関数であ
る.

!C関数ヘッダ行の変換
C関数ヘッダ行
type fname (type1 var1, ..., typen varn) {
を以下の形のSML#の束縛構文に変換する.
val fname = bind "fname" : _import (type1, ..., typen) -> type ;
Emacsになれた者は,置換とキーボードマクロ機能を使えば以下の手順で機械的に実現でき
る.
# { を -> で置き換える.
# 以下のキーボードマクロを定義
## 最初の行にカーソルを合わせる
## (キーボードマクロスタート)C-x (
## (カーソルを先頭に移動)C-a
## (帰り値型を末尾に移動)M-k C-e C-y
## (関数名をkill)C-a  M-f M-f Mーb M-k
## (val宣言)M-k val C-y = bind " C-y " : _import
# (キーボードマクロ終了)C-x )
以上で,
type fname (type1 var1, ..., typen varn) {

val fname = bind "fname" : _import (type1 var1, ..., typen varn) -> type
の形に変換するキーボードマクロが定義される.ここキーボードマクロをC-xe
で必用な回数呼び出せば,全ての行がこの形に変換される.
これに続き,var1, ..., varnを消去すれば,SML#の動的ライブラリ束縛
構文が得られる.

!ファイルをセーブする.
本例では以下の内容のファイルex1.smlができる.
val dlName = "ex1.dll";
val dllLib = DynamicLink.dlopen(dlName);
fun bind fName = DynamicLink.dlsym(dllLib,fName);
val shou = bind "shou" : _import (int, int) -> int;
val amari = bind "amari" : _import (int, int) -> int;
val sigmaN = bind "sigmaN" : _import (int, int) -> int;
val sigmaN2 = bind "sigmaN2" : _import (int, int) -> int;
val  A = bind "A" : _import (int, int, int) -> int;
val B = bind "B" : _import (int, int, int) -> int;
val C = bind "C" : _import (int, int, int, int) ->  int;
val fib = bind "fib"  : _import (int) ->  int;

作成されたファイルはSML#のライブラリファイルに置かれるので,
どこかれでも
use "ex1.sml";
以下のように文で参照できる.
c:\SMLSharpAndC\sml>smlsharp
smlsharp
SML# 0.30 (2007-07-03 16:16:12 JST)
# use "ex1.sml";
val dlName = "ex1.dll" : string
val dllLib = 0x10000000 : unit ptr
val bind = fn : string  -> unit ptr
val power = fn : int * int  -> int
val shou = fn : int * int  -> int
val amari = fn : int * int  -> int
val sigmaN = fn : int * int  -> int
val sigmaN2 = fn : int * int  -> int
val A = fn : int * int * int  -> int
val B = fn : int * int * int  -> int
val C = fn : int * int * int * int  -> int
val fib = fn : int  -> int
# power(2,3);
val it = 8 : int
# shou(23,7);
val it = 3 : int
# amari(23,7);
val it = 2 : int
# fib 10;
val it = 89 : int
#

! ツールの利用
以上の手順を実行してみると理解される通り,機械的に作成できるので
この手順を実行するツールを構築できる.近い将来そのようなツールを
公開予定である.ツールを使えば,C関数が入ったファイル名を指定する
だけで,その関数がSML#の対話環境から使用できるようになる.

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