SML# - Language/FFI/Ffiapply Diff

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

Cで定義された型依存の振る舞いをする関数などをSML#から呼び出すための低
レベルな構文である.以下の文法を持つ.
_ffiapply <exp> (<arg>, ..., <arg>) : <ty>
ここで,
* ''<exp>'' はunit ptr型のCの関数ポインタ式,
* ''<arg>'' はCに渡す引数の指定,
* ''<ty>'' は返り値の型である.
各引数は以下の文法で指定する.
:式と型の指定:
<arg> ::= <exp> : <ty> | _sizeof(<ty>)
ここで,
* ''<exp> : <ty>''はC関数に渡す式とその型の指定
* ''_sizeof(<ty>)'' はSML#が管理する型''<ty>''の表現サイズ情報の参照である.この特殊構文は,コンパイラによって型のサイズを表す式に自動的に置き換えれる.
* ''<ty>'' は任意の[[相互運用型|Language/FFI/Types]]を指定できる.

!!例
例えば,Cのライブラリ関数qsort(3)は以下のように呼び出すことができる.
  val libc = DynamicLink.dlopen "/lib/libc.so.6"
  val c_qsort = DynamicLink.dlsym (libc, "qsort")
  fun qsort (a, f) =
      _ffiapply c_qsort (a : 'a array,
                         Array.length a : int,
                         _sizeof('a),
                         f : ('a ptr, 'a ptr) -> int) : unit
関数の引数は配列aと比較を行うコールバック関数である.
関数本体で,C関数に,配列の要素数と配列の要素のサイズを渡している.
これによって,qsortは,ポインター操作による効率よいinplaceクイックソー
トを行う.この定義によって以下の型の関数が生成される.
val qsort : ['a. 'a array * ('a ptr * 'a ptr -> int) -> unut]


!!注意
この構文を用いたC関数の呼び出しの定義は,SML#の型主導コンパイルの結果
のC関数呼び出し式をコーディングしていることに相当する.
この式を書くプログラマは,これら引数の数,その順序および型が実際のC関
数の仕様と一致していることを確認する必用がある.

その一致が保証されれば,qsortのようなポインタを操作する低レベルの関数
も,SML#からデータ変換などのオーバヘッド無に,しかも型安全に直接呼び
出すことができる.