日本ソフトウェア科学会第 33 回大会 (2016 年度) 講演論文集

SML#のよりシームレスな外部関数インターフェースの実現に向けて
佐藤 友昭

上野 雄大

大堀 淳

本稿では，関数型言語 SML#においてよりシームレスに C 関数をインポートする際の残された問題とその解決策を提案する．SML#には，C 関数を相互に呼び出せる外部関数インターフェースが実装されており，多くの C 関数を特別なデータ変換をせずに直接インポートできる．しかし現在の SML#ではサポートされていない C の型があり，それらを扱う関数をインポートできない．本稿では特に，特定の使い方をする共用体を代数的データ型に対応付けることで，共用体を扱う関数のインポートを試みる．また，巨大な構造体へのポインタを受け取る関数や引数の数が多い関数をインポートする際，関数型の可読性が低くなることがある．本稿では順序付きレコード型を導入し，引数やメンバの並びをラベル付きの型で表現する方法を提案する．これらの拡張により，多量のコールバック関数やイベント共用体を引数にとる GUI ライブラリ等も直接インポート可能となり，SML#の実用性の向上が期待できる．

を以下に列挙する．

1 はじめに

1. 構造体へのポインタ型を SML#のタプル型に関数型言語 SML# [1] には外部関数インターフェー対応付けているため，C の構造体型が持つメンバス（Foreign Function Interface : FFI）が実装され名が SML#では失われる．このため，SML#プており，多くの C で書かれた関数をスタブコードなログラムの可読性が大きく損なわれる．

どの特別なデータ変換処理を書かずに直接インポー

2. C 関数の引数の並びを SML#のタプル型に対トすることができる [3]．我々はこの FFI を用いて，応付けているため，同じ型の引数が複数並んでい

SMT ソルバの一種である Z3 [2] などの多くの C のラる時に，ユーザはその型から各引数の意図を区別

イブラリ関数を SML#にインポートすることを試みすることが難しい．

た．その過程で，ほとんどの C 関数は自然にインポー

3. FFI では対応していない C の型が存在し，そのトできた一方，いくつかの C 関数は SML#の FFI の型を使う C 関数をインポートできない．特に共機能不足のためそのままインポートすることができ用体型がサポートされていない．

なかった．また，たとえインポートできたとしても，本論文では，第 1，第 2 の課題に対する解決策を提案

インポートした C 関数の SML#での型が，C 関数をし，その解決策に基づき行った SML#の変更につい使いこなすために有用な情報を含まないため，C 関て報告する．

数を使用する SML#プログラムの書きやすさや可読

これらの課題に対する本論文での分析は以下の通性に難があることがあった．具体的な改善すべき項目りである．第 1 の問題の根幹は，C の構造体型はメンバ名を型に含む一方で，SML#の FFI ではそれらTowards Implementation of A More Seamless Foreign
Function Interface in SML#
Tomoaki Sato, 東 北 大 学 情 報 科 学 研 究 科, Graduate
School of Information Sciences, Tohoku University.
Katsuhiro Ueno, Atsushi Ohori, 東北大学電気通信研究所, Research Institute of Electrical Communication,
Tohoku University.

メンバ名を捨てていることにある．C の構造体型の各メンバはその名前と型からなる．このような構造と自然に対応する SML#の型はレコード型である．しかし，SML#の FFI は構造体型をタプル型に対応付けている．その理由は，C の構造体ではメンバは宣言された順序で並ぶのに対し，SML#のレコード型はを述べる．第 3 の課題については，FFI を拡張するフィールドの並びが順不同だからである．もしレコー

方針を述べる．

ドとタプルの両方の特徴を併せ持つ，フィールドの名

本稿の構成は以下の通りである．2 節では，順序付前と並び順の両方を区別するレコード型を SML#にきレコード型の構文とフィールドの順序の決め方を説導入すれば，その型は構造体とより厳密に対応するは明する．3 節では，順序付きレコードによって C 関ずである．本論文ではラベルの順序と名前の両方の情数の引数の並びを表現する方法を述べる．4 節では，報を含む新しいレコード型を SML#に導入すること共用体型をヴァリアント型に対応付けるための方針をを提案する．以下，本論文ではこのレコードを順序付述べる．最後に 5 節でまとめと今後の予定を述べる．

きレコードと呼ぶ．
第 2 の問題も，第 1 の問題と同様に，タプル型

2 順序付きレコード型の導入がフィールドに名前を付けないことに原因がある．

本節では，フィールドの順序をラベルの一部としてSML#の FFI は複数引数を持つ C 関数を SML#に指定することができる順序付きレコード型を導入す

インポートする際，その引数の並びをタプル型で表る．順序付きレコード型は以下のように書く．

現する．従って，C 関数が同じ型の引数を複数個とる{l1 :τ1 ,. . ., ln :τn }場合，ユーザーはそれらの引数の意図を SML#の型

ここで，順序付きレコード型のラベル li は，自然数とから読み取ることが難しい．同様の問題は C にも存

名前をアンダーバー（ ）でつなげたものである．こ在するものの，C では関数のプロトタイプ宣言に仮の自然数がフィールドの順序を表す．順序付きレコー

引数の名前を書くことを許すため，SML#のタプル

ドのフィールドは，その名前にかかわらず小さな数字型よりもユーザーにとって読みやすい関数の型を書から順番に並ぶ．例えば，順序付きレコード型

くことができる．もし SML#にインポートした C 関{1 name :string, 2 age :int}

数の SML#での型にも，仮引数の名前を含めることは，最初のフィールドが string 型で，次のフィールができれば，より読みやすく使いやすい FFI になる

ドが int 型であるようなレコードの型である．順序と期待できる．そこで本論文では，順序付きレコード付きレコードを生成する式は，ラベルの部分を除いてを C 関数の引数の並びの型にも応用することで，こ通常のレコード式と同様である．の問題の解決を試みる．

1 節で述べたように，順序付きレコード型はフィー

第 3 の問題を解決するためには，C の共用体型とルドの並び順と名前の両方を持つため，C の構造体型対応する機能を有し，かつ互換性のある内部表現を持と自然な対応がある．我々は，インポートする C 関

ち得る SML#の型を，FFI が共用体型と対応付ける数の引数の型に順序付きレコード型を書けるようにSML#の型と定義し，その対応が満たされるようなFFI を拡張した．C 関数が引数として構造体へのポコードが生成されるように SML#の FFI 方式を拡張

インタを受け取る時，ユーザはその引数の型として順する必要がある．C の共用体型は，メンバとして指定序付きレコード型を書くことができる．順序付きレされた複数の型のうちいずれかひとつをデータ表現とコードは，それと自然に対応する構造体と同じメモする型である．この状況に自然に対応する SML#のリ上のデータ表現を持つ．C 関数を呼び出す時，こ型はヴァリアント型である．もし，FFI でサポートすのデータ表現へのポインタが C 関数に渡される．例

る共用体の使い方をヴァリアントと同様な使い方に限えば，C の標準ライブラリ関数である asctime 関数

定するならば，SML#のデータタイプを共用体と見は以下の図 1 のようにインポートすることができる．

なすことができるはずである．

asctime は，日時を表す構造体へのポインタを受け

本論文では，第 1，第 2 の課題について，上述した取り，その構造体に格納されている日時を文字列へと方針に基づく SML#の FFI の拡張方式と，その拡張変換する関数である．図 1 に示すように，順序付きレ方式に基づく SML#コンパイラの改良に関する概要

コード型を導入することで拡張した FFI では，構造$ smlsharp$ smlsharp# val asctime =# type FILE = unit ptr_import "asctime" :> val fopen ={1_sec : int, 2_min : int,

_import "fopen" :3_hour : int, 4_mday : int,

(1_filename : string, 2_mode : string)

5_mon : int, 6_year : int,-> FILE

7_wday : int, 8_yday : int,

type file = unit ptr

9_isdst : int}

val fopen =-> char ptr

fn : {1_filename: string, 2_mode: string}

val asctime =-> unit ptr

fn : {1_sec: int, 2_min: int,
3_hour: int, 4_mday: int,#
図2

提案手法を用いた C 関数のインポート例

5_mon: int, 6_year: int,
7_wday: int, 8_yday: int,
9_isdst: int}を含むことができるように，以下の構文を追加する．

import "f " :(l1 :τ1 ,. . ., ln :τn ) -> τ

この式に対する型付けの方針はいくつか考えられる．

-> char ptr

その中の 1 つの方針は，C のように引数名を捨て，型#
図1

構造体へのポインタを受け取る C 関数のインポー
ト例

情報のみを含む関数型を作る方法である．インポートした関数をユーザが SML#で利用する際の利便性を考慮すると，関数型に引数名の情報が含まれている方体へのポインタを受け取る関数をその構造体のメンバが望ましい．そこで我々はこの式に対して型付けを行名を失うことなくインポートすることが可能である．

う際に，その関数の引数型に順序付きレコード型を対

順序付きレコードの実装は，レコードラベルの集応付ける．li を順序付きレコードのラベルとする時，合に，順序付きのラベルを加えることで行った．ラベ

この式は以下の型を持つ．

ルに基づくフィールドの並べ方を除けば，順序付きレ{l1 :τ1 ,. . ., ln :τn } -> τ

コードのコンパイルは通常のレコードのコンパイル

本手法による C 関数のインポート例として，図 2 にと同様である．SML#コンパイラは実行時のデータ

標準ライブラリ関数 fopen をインポートするコード

形式を確定するために，レコードラベルの集合が，全を示す． 関数 fopen は，const char*型の filename順序集合となるように内部的に順序を定義した．と mode を受け取り，指定されたモードで開かれたファイルへのポインタを返す関数である．図 2 に示す

3 順序付きレコードによる引数の並びの表現

ように，我々はこの関数を順序付きレコード型を受け

SML#で C 関数をインポートするには，以下のよ

取り unit ptr 型を返す関数型としてインポートする

うな式をプログラムに記述する．

import "f " :(τ1 ,. . ., τn ) -> τことができる．このことによって，同じ string 型を持つ 2 つの引数をファイル名とモードで区別するこ

この式は，n 個の τ1 ,. . ., τn 型の引数を受け取り τ 型とが可能となり，従来に比べてより便利に SML#にの値を返す C 関数 f を以下の型を持つ SML#の関数インポートした関数を使うことができる．

としてインポートすることを意味する．

τ1 * · · · * τn -> τ
我々は，SML#にインポートする関数の型に引数名

4 共用体型とヴァリアント型の対応付け
1 節で述べたように，共用体型は SML#のヴァリアント型に対応付けられると期待できる．SML#のヴァリアント型の値は，どのヴァリアントが選択されているかを表すタグをそのデータの先頭に含む．一方

5 まとめ

で共用体型は，その共用体の先頭にタグを含むとは限

本稿では，順序付きレコード型を SML#に導入すらない．つまり，共用体型とヴァリアント型は同様のる方法を述べた．この順序付きレコード型の導入に機能を有する反面，メモリレベルのデータ表現には厳よって，SML#がより構造体のデータ表現に近い型を密な互換性がない．この非互換性は，共用体型の方が持つように拡張された．また，順序付きレコード型をヴァリアント型よりも自由なデータ表現を取り得るこ

C 関数の引数の並びに対応付けることで，SML#にとに起因する．

インポートした関数の型に引数名を含めることがでヴァリアント型のデータ表現と対応する使われ方をき，ユーザはより便利に SML#にインポートした関する共用体型については，SML#に自然にインポート数を利用できることを示した．さらに，共用体型をすることができると考えられる．そこで我々は，共用SML#のヴァリアントに対応付けるための方針を述

体のメンバの先頭に 32 ビット整数のタグを含む場合べた．に限り，この共用体を SML#のデータタイプとして今後は，共用体を SML#にインポートするためのインポートすることを許すことを検討している．このコンパイル方式などを含む詳細な実装方針を定め，ような共用体のインポートを実現するためには，ユーFFI に組み込む予定である．

ザがタグとして指定する整数値が SML#のデータタ

謝辞 本研究の一部は JSPS 科研費 25280019「MLイプのどのヴァリアントに対応するかを決定しなけれ系多相型言語 SML#の実用化技術に関する基礎研究」

ばならない．FFI の方針としては，この判断はユーザおよび 15K15964「実用プログラミング言語のためのの責任に基づき行われるべきである．つまり，それぞ系統的言語開発基盤の実現」の助成を受けて実施されれの整数タグがどのヴァリアントに対応するかを制御たものである．

できるような仕組みが SML#に実装されたとするな
らば，SML#に共用体をインポートし利用すること

参 考 文 献ができると思われる．

[1] : SML# プロジェクト, http://www.pllab.riec.tohoku.ac.jp/smlsharp/ja/.
[2] : Z3 C API, http://z3prover.github.io/api/html/group capi.html.
[3] 上野雄大, 大堀淳: SML# の外部関数インターフェー
ス, コンピュータソフトウェア, Vol. 27, No. 2(2010),
pp. 142–168.