To Home
Created: Mon Jul 29 15:07:46 JST 2002
Last modified: Tue Dec 26 14:56:15 JST 2006
CamlIDL
概要
CamlからCのコードを呼ぶためのスタブコード生成器
使うために
入力ファイルの拡張子は .idl
Cのプロトタイプ宣言にちょっと(?)情報を付加したもの。
コメントは // , /* */ のようにC++スタイルである。
観察
quote(C,"[cのコード]") で Cのコード埋め込み
quote(call,"[cのコード]") で関数が呼び出された直後に埋め込むコードを指定できる。
↑ call/C のほかに....?
idlファイルから *_stubs.c を生成する。
[] 内に種々の制約情報をいれる。 in, out, サイズの情報など
いれられるものたち (Attributes)
ひきすうのみならず返り値にも指定する。(string, string*, null_terminated ...)
- set .. enumらしい
- in
- out
- string
- string* .. argv,envなど
- null_terminated (string* の終了は NULLである)
- size_is(int)
- length_is(?)
- switch_is(?)
- abstract .. typedefとともに
- unique
例と共に
tests/unix.idl
char** environment(void) で quote(call,"_res = environ;");
と変数束縛を行なうコードを埋め込んでいるが....。
なぞ _res って?
なぞ environ って?
解答 environ
直前に長い quote(C,"...") がありこの中で environは宣言されている。
extern char ** environ;
解答? _res
対応するスタブコード value camlidl_unix_environment(value _unit)
の中で宣言されている。 _res は返り値(Cの表現)を入れる局所変数のようだ。
変数の命名規則?? (返り値のみでよいような気も??)
3.9 Functions で _res について述べられている。
callは、関数呼出部分を自分で書くためのもの。
スタブコードは以下の手順を踏む
- 前処理: 引数をMLの表現からCの表現へ変換
- 対応するCの関数を呼び出す
- 後処理: 返り値をCの表現からMLの表現へ
この、対応するCの関数 は idl の中で書かれた関数である。この対応する関数の
呼出をカスタマイズするのが quote(call,"..")である。
例 普通の呼出
unix.idlから拝借 unix.idlでの unlink
int unlink([string] char * filename);
|
スタブコード。これは普通に unlink を呼ぶ。
value camlidl_unix_unlink(
value _v_filename)
{
char *filename; /*in*/
int _res;
/* 前処理 caml から C へ */
value _vres;
filename = String_val(_v_filename);
/* 呼出 */
_res = unlink(filename);
/* 後処理 C から caml へ*/
_vres = Val_int(_res);
return _vres;
}
|
例 quote(call,"..")をつかうもの
unix.idlから拝借 unix.idlで environment は以下のように書かれている。
[string*, null_terminated] char ** environment(void)
quote(call, "_res = environ;");
|
environ は extern 宣言されている。どこで確保されてるんだろうねぇとおもって
man environ を実行すると。あった。 おまけ
これは quote(call,"..") があるので、 environment 関数を呼ぶのではなく
結果に environ を入れる。スタブコードは以下のとおり。
value camlidl_unix_environment(value _unit)
{
char **_res;
mlsize_t _c1;
mlsize_t _c2;
value _v3;
value _vres;
/* begin user-supplied calling sequence */
_res = environ;
/* end user-supplied calling sequence */
_c1 = camlidl_ptrarray_size((void **) _res);
_vres = camlidl_alloc(_c1, 0);
Begin_root(_vres)
for (_c2 = 0; _c2 < _c1; _c2++) {
_v3 = copy_string(_res[_c2]);
modify(&Field(_vres, _c2), _v3);
}
End_roots()
return _vres;
}
|
なぞ (Ocaml内部で使われているマクロ? 関数??)
Begin_root(int)
End_roots()
camlidl_alloc_small(int,int)
Field(value,int) = .. (left value)
camlidl_find_enum
Int_val : MLのint → Cのint (value of int ってところ?)
Val_int: Cのint → MLのint
イメージ
idl, MLから呼びたいCコード
↓
ml, mli 型と external 宣言。実際どのCの関数と対応するか?
*_stab.c MLのオブジェクトを C のオブジェクトに変換。
関数呼出。
返り値をMLのオブジェクトに戻す
producer.cは提供したいライブラリ []で括られるものは producer.idl から
生成されるファイル
consumer.ml → [producer.{ml,mli}] → [producer_stabs.c] → producer.c
call external call
しばし内部を除き見する
compilerディレクトリに本体がある。依存性を見ると結構複雑。ファイルも多い。
Cのヘッダににているidlファイルを読んでいる場所はどこかな?
clflags.mlはスイッチになる変数がはいっているだけ
process_comp 内で処理。パターンマッチ
Comp_typedecl, Comp_structdecl, Comp_uniondecl, Comp_enumdecl, Comp_fundecl, Comp_constdecl, Comp_diversion??, Comp_interface, Comp_import
File.component型である↑
パーザーは parse_aux.mlなど...
parser_midl.mly, lexer_midl.mll, linenum.mll はOcaml{Yacc,Lex}で自動生成した
パーザーと字句解析器
予想
+--字句解析------+ +--構文木生成-----+ +--構文木生成-----+
| lexer_midl.mll | → | parser_midl.mly | → | parser_midl.mly |
| | | | | |
+----------------+ +-----------------+ +-----------------+
parse.mlないで Parser_midl.fileを使用している
parse_auxってなんだ?
ocamlとともに
実際に使ってみる。まず、compilerディレクトリの中のファイルたちをまとめてバイト
コードライブラリ (.cma) にしたい。そこで、こんな
Makefileを書く。
> make bcl
成果物である files.cma を tests ディレクトリにもっていって、そこで遊ぶ。
例えば↓ -I でインターフェイスファイルのパス指定。
> ocaml -I /home/tak/download/camlidl-1.04/compiler/
Objective Caml version 3.06
# #load "files.cma";;
# let input = open_in "arrays.idl";;
val input : in_channel = <abstr>
# let lb = Lexing.from_channel input ;;
val lb : Lexing.lexbuf =
...
# let res = Parser_midl.file Lexer_midl.token lb;;
val res : File.components =
[File.Comp_fundecl
{Funct.fun_name = "str1"; Funct.fun_mod = "";
Funct.fun_res =
Idltypes.Type_array
({Idltypes.bound = None; Idltypes.size = None; Idltypes.length = None;
Idltypes.is_string = true; Idltypes.maybe_null = false;
Idltypes.null_terminated = false},
Idltypes.Type_int (Idltypes.Char, Idltypes.Iunboxed));
Funct.fun_params =
[("s", Funct.In,
Idltypes.Type_array
...
使用例
上の説明とはまったくつながっていません。 libinn (The InterNetNews library) の
parsedate を呼ぶスタブ。 ocamlmklib を用いてライブラリも作ってみました。
parsedate-2003-08-06.tar.gz
リンク
CamlIDL
作者: 増山隆
To Home