=encoding euc-jp =head1 名前 Inline::C - CでPerlサブルーチンを作成 =head1 説明 C は、CでPerlサブルーチンを作成することを可能にするモジュールです。バージョン0.30から、Inlineモジュールは複数のプログラミング言語をサポートし、各言語はそれぞれ独自のサポートモジュールを持ちます。このドキュメントはプログラミング言語CでInlineを使う方法について説明します。それはPerl C内部にも少しだけ入っていきます。 今すぐプログラムの例を試してみたいのであれば、Lを試してみてください。Inline全般については、Lをご覧ください。 =head1 使用方法 実際にはCを直接使うことはありません。これは単にCをCで使うためのサポート・モジュールに過ぎません。そこで使い方は常に以下のようになります: use Inline C => ...; あるいは bind Inline C => ...; =head1 関数定義 CのためのInline文法はあなたCのコードでの特定の関数定義(あるいは記述)を解釈します。記述がInlineによって解釈されると、それがPerlの空間で利用できるようになります。つまり、Inlineはその関数をPerlサブルーチンであるかのように呼び出すために必要な"糊"の部分を生成します。もし記述が理解できなければ、Inlineはそれを単に無視するだけです。何も言いません。それはPerlの空間からは利用することはできません、それがたとえCの空間からは利用できたとしても。 InlineはANSI/プロトタイプ形式の関数定義を検索します。それは以下のような形式になります: 戻り値のデータ型 関数名 ( データ型-名前の組み合わせの集合 ) { ... } よく使われるデータ型は:C, C, C, C, そして Cです。しかし、あなたはInlineがtypemapで見つけることができるすべての型を使うことが出来ます。InlineはデフォルトでPerlと一緒に配布されるCを利用します。あなたはTYPEMAPSコンフィグレーション・オプションでさらに多くのtypemapを指定することができます。 Cという戻り値のデータ型も利用することが出来ます。以下に正しい関数定義の例を示します。 int Foo(double num, char* str) { void Foo(double num, char* str) { SV* Foo() { void Foo(SV*, ...) { long Foo(int i, int j, ...) { 以下の定義は理解されません: Foo(int i) { # 戻り値の型がありません int Foo(float f) { # floatの(デフォルトの)typemapはありません unsigned int Foo(int i) { # 'unsigned int' は理解されません int Foo(num, str) double num; char* str; { void Foo(void) { # void は戻り値の型としてだけ有効です Inlineは、関数のI<プロトタイプ>ではなく、関数のI<定義>だけを検索することに注意してください。定義は関数本体の直接前にある書き方です。またInlineはヘッダのような外部ファイルも調べません。ライブラリはリンクすることができますし、Cの空間から呼び出すことが出来ます;しかしInlineに渡されたコードだけが、結びつけのために使われます。 =head1 C 構成設定オプション Inline構成設定オプションを指定する方法の情報については、Lをご覧ください。このセクションでは、Cのために利用できる各構成設定オプションについて説明します。ほとんどのオプションが同じ名前のMakeMakerあるいはXSのオプションに対応します。L と Lをご覧ください。 =head2 AUTO_INCLUDE 自動的にインクルードされる追加のステートメントを指定します。それらはデフォルトに追加されます。改行文字が自動的に追加されます。 use C => Config => AUTO_INCLUDE => '#include "yourheader.h"'; =head2 AUTOWRAP もし'ENABLE => AUTOWRAP'とすれば、Inline::CはあなたのCのコードの中の関数宣言(プロトタイプ宣言)を解析します。それがバインドできる各宣言について、外部ライブラリにあるかもしれない本当の関数を呼び出すダミーのラッパーを生成します。これはそうでなければ空のラッパー関数を必要とするだけの関数のためには、とても便利です。 これはCから取得できる基本的な機能と同じです。これは外部ライブラリとバインドするためにはとても有効でしょう。 =head2 BOOT XS BOOTセクションで実行されるCのコードを指定します。XSのパラメータに対応します。 =head2 CC 使用するコンパイラを指定します。 =head2 CCFLAGS 追加のコンパイラ・フラグを指定します。 =head2 FILTERS ソースコード・フィルタのリストを指定することを可能にします。1個以上が要求されるのであれば、配列リファレンスでそれをまとめるようにしてください。フィルターはサブルーチンのリファレンスあるいは、補足のInline::Filtersモジュールによって提供されるフィルタの名前にすることができます。 あなたのソースコードはInlineによって解析される直前にフィルターに掛けられます。フィルタに掛けられる前に、MD5フィンガープリントが作成されます。ソースコード・フィルタはPODドキュメントの取り外し、#includeステートメントの事前展開など、あなたの好きなことをするために使うことが出来ます。例えば: use Inline C => DATA => FILTERS => [Strip_POD => \&MyFilter => Preprocess ]; フィルタは指定された順番に呼び出されます。さらなる詳細はLをご覧ください。 =head2 INC 利用するインクルードパスを指定します。MakeMakerのパラメータに対応します。 use C => Config => INC => '-I/inc/path'; =head2 LD 使用するリンカを指定します。 =head2 LDDLFLAGS 使用するリンカ・フラグを指定します。 注意: このフラグは単に追加するのではなく、完全に既存のフラグを上書きします。そのため、それらも使用する必要があるのであれば、それらをここで再び指定してください。 =head2 LIBS あなたのコードにリンクされるべき外部ライブラリを指定します。MakeMakerのパラメータに対応します。 use C => Config => LIBS => '-lyourlib'; あるいは use C => Config => LIBS => '-L/your/path -lyourlib'; =head2 MAKE 使用する'make'ユーティリティの名前を指定します。 =head2 MYEXTLIB リンクされるべき、ユーザがコンパイルしたオブジェクトを指定します。MakeMakerのパラメータに対応します。 use C => Config => MYEXTLIB => '/your/path/yourmodule.so'; =head2 OPTIMIZE これはMakeMaker OPTIMIZE設定を制御します。この値を'-g'に設定することにより、あなたはInline拡張のためのデバッグ・サポートが有効になります。これによりgdbのようなデバッガを使ってあなたのCのコードにブレークポイントを設定することが可能になります。 =head2 PREFIX それらがPerlに結び付けられたとき、Cの関数から外されるプレフィックス(prefix)を指定します。共有ライブラリAPIのためのラッパーを生成し、Perlでの元の名前に結びつけるために便利です。またPerlの内部関数と名前がぶつかるときにも便利です。XSのパラメータに対応します。 use C => Config => PREFIX => 'ZLIB_'; =head2 TYPEMAPS 利用する追加のtypemapファイルを指定します。これらのデータ型はCの解析の動きを変えます。MakeMakerのパラメータに対応します。 use C => Config => TYPEMAPS => '/your/path/typemap'; =head1 CとPerlの結びつけ この関数はCの変数がCの変数に相互に、どのように対応付けられるのかについて説明します。 まず、あなたはCがどのようにサブルーチンに引数をやり取りしているかを知っておく必要があります。基本的に、それはスタックを使用します(Bとしても知られています)。subが呼ばれたとき、丸括弧の中の全ての引数はスカラのリストに展開されます。そしてBにプッシュされます。そしてサブループンはBから、そのパラメータをポップします。subが終了するとき、それはその全ての戻り値をBにプッシュして戻します。 Bは、内部的にはCで知られているスカラの配列です。実際にBは、BあるいはCの配列です;このためBの各要素は、本来、Cなのです。これについてのIは、Cをご覧ください。 そこで変数の対応に戻ります。XSは"typemaps"として知られている物を、各CをCデータ型に変えたり戻したりするために使用します。これはさまざまなXSマクロ呼び出し、キャスト、そしてPerl APIを通して成し遂げられます。Cをご覧ください。XSは、Cで定義されたstructのように、より凝った標準ではないデータ型のために、あなたがあなた自身のtypemapを定義することを可能にします。 Inlineは、デフォルトのPerl typemapファイルをそのデフォルトのデータ型のために使用します。このファイルはC、あるいはあなたのPerlインストール方法によって、それに似たものになります。それには40種類以上のデータ型が入っています。それらは自動的にInlineによって使われます。(何か可能かをしるために、一度はこのファイルを見ておくべきでしょう。) Inlineは、これらのデータ型のためにあなたのコードを解析し、それらを対応付けるためのXSコードを生成します。最もよく使われるデータ型は以下のものです: - int - long - double - char* - void - SV* デフォルトに入っていないデータ型を扱う必要があるのであれば、単に一般的なCデータ型を関数定義で使ってください。そして、あなたのコードの中で、あなた自身が対応付けてください。代わりとして、あなた自身のtypemapファイルを生成し、C構成設定オプションを使って指定することができます。 戻り値のデータ型の1つCはInlineには特別な意味を持っています。それはBにあなた自身が返す値をプッシュしようとしているという意味になります。これは値のリストを返す必要があるということです。もしあなたは本当に何も返したくないのであれば(Cの昔ながらの意味)、単に何もプッシュしないでください。 もし省略やC<...>が引数リストの末尾で使われれば、それは任意の数のCが続くかもしれないという意味になります。ここではあなたはCの値をあなた自身がポップして取り出す必要があります。 下記のL<"例">をご覧ください。 =head1 Inline Stack マクロ Inline Cを書くとき、(デフォルトでは)以下の行が自動的にあなたのコードの前につけられます: #include "EXTERN.h" #include "perl.h" #include "XSUB.h" #include "INLINE.h" ファイルCは、Perl StackをCの関数から扱うために便利なマクロが定義されています。 =over 4 =item Inline_Stack_Vars もしあなたが他の物を使いたいのであれば、これを使う必要があります。これは他のマクロによって使われる、いくつかのローカル変数を設定します:C, C, C and C。それが何であるかは重要ではありません。しかし名前の衝突の可能性を避けるために、それに触れています。 注意: このマクロは変数を宣言するので、あなたの他の変数宣言と一緒に関数の先頭に置いておく必要があります。それは実行ステートメントの前、そして他のCマクロよりも前になければなりません。 =item Inline_Stack_Items Stackに渡された引数の数を返します。 =item Inline_Stack_Item(i) Stackでの特定のCを参照します。Cは0始まりのインデックス番号です。値を取得や設定ために使うことが出来ます。 =item Inline_Stack_Reset Stackに何か値をプッシュして戻す前に使ってください。これはStackの内部ポインタをStackのはじめにリセットします。 =item Inline_Stack_Push(sv) Stackに戻り値をプッシュします。値のデータ型はC型でなければなりません。 =item Inline_Stack_Done 戻り値の全てをプッシュした後、このマクロを呼ばなければいけません。 =item Inline_Stack_Return(n) StackでのCの要素を返します。 =item Inline_Stack_Void あなたが本当に何も返さないことを示す特殊なマクロです。以下のものと同じです: Inline_Stack_Return(0); このマクロは実際に、あなたの関数からB<リターンする>ことに注意してください。 =back これらのマクロは、あなたのコーディングの好みに合わせて異なる3つの形式で使うことが出来ます。以下の以下のマクロはすべて同等です。 Inline_Stack_Vars inline_stack_vars INLINE_STACK_VARS この機能のすべてはXSマクロ呼び出しを通しても利用することができます。それではなぜ機能が重複しているのでしょうか?なぜ私がこの一連のマクロを提供するように決めたのかという理由はいくつかあります。第一にStackへアクセスするための便利な方法として。第二に一貫性があり自己説明的であり分かりにくくないコーディングのために。第三に将来の互換性のために。それは彼らのCのコードのために、多くの人がXSマクロを使いはじめたならば、Perl6ではそのインターフェースが崩れてしまうかもしれないと思われました。このセットを使うことにより、たぶん引数の取扱いでの将来の互換性を保証することが出来ます。 もちろん、あなたが他のPerl APIを使えば、あなたのコードはおそらくPerl6の下では崩れてしまうでしょう。そのためこれは100%の保証ではありません。しかし引数の取扱いは最もよく、あなたが使いそうなインターフェースですから、そうすることが賢いことのようにみえます。 =head1 Cのサブルーチンの書き方 あなたのC関数の定義は以下の4つのカテゴリのどれか1つに入ります。各カテゴリ毎に特に注意する点があります。 =over 4 =item 1 int Foo(int arg1, char* arg2, SV* arg3) { これが最も単純なケースです。戻り値のデータ型がCではなく、固定した数の引数リストを持っています。あまり心配する必要はありません。すべての変換は自動的に行われます。 =item 2 void Foo(int arg1, char* arg2, SV* arg3) { このカテゴリでは、戻り値の型がCです。つまりあなたは何も返したくないか、リストを返したいという意味です。後者のケースでは、あなた自身でBに値をプッシュする必要があります。これを簡単に行うためのInlineマクロがいくつかあります。コードは以下のようになります: int i, max; SV* my_sv[10]; Inline_Stack_Vars; Inline_Stack_Reset; for (i = 0; i < max; i++) Inline_Stack_Push(my_sv[i]); Inline_Stack_Done; Stackポインタをリセットした後、このコードは一連の戻り値をプッシュします。最後に戻り値のスタックの最後をマークするためCを使います。 あなたが本当に何も返したくないのであれば、Cマクロを使わないでください。あなたがそれを使ったならば、関数の最後でCを使って設定してください。 =item 3 char* Foo(SV* arg1, ...) { このカテゴリでは、引数の数が決まっていません。つまりBからあなた自身が値をポップする必要があるということです。以下のようにしてください: int i; Inline_Stack_Vars; for (i = 0; i < Inline_Stack_Items; i++) handle_sv(Inline_Stack_Item(i)); Cの戻り値のデータ型はCです。 =item 4 void* Foo(SV* arg1, ...) { このカテゴリでは、戻り値の型としてCを持ち、引数の数が決まっていません。単に、カテゴリ3と4からのテクニックを組み合わせてください。(訳者注:これは2,3の間違いでしょう) =back =head1 例 以下にいくつかの例を挙げます。それぞれ、あなた自信が実行して試すことができる完全なプログラムです。より多くの例についてはLをご覧ください。 =head2 例 #1 - 挨拶(=Greetings) この例は1つの文字列の引数(名前)を取り、挨拶を出力します。関数は文字列と数値で呼び出されます。2番目のケースでは数値は文字列へ強制的に変換されます。 C<#include >とする必要がないことに注意してください。デフォルトでインクルードされるCヘッダ・ファイルは、自動的に標準的なCのヘッダファイルをあなたに代わってロードします。 use Inline C; greet('Ingy'); greet(42); __END__ __C__ void greet(char* name) { printf("Hello %s!\n", name); } =head2 例 #2 - さらに挨拶の言葉 これは、文字列(C)ではなく、名前(=name)がC(スカラ値(=Scalar Value)へのポインタ)である点を除けば、上記の例に似ています。つまりCを文字列に自分自身で変換する必要があるということです。これはC内部APIの一部であるC関数を使うことにより実現できます。さらなる情報についてはCをご覧ください。 問題はCが自動的に文字列を数値に変換しないことです。そのためC<42>に挨拶しようとすると、ちょっとビックリすることになります。このプログラムは、Perlの内部をいじったときによく発生するように、セグメント・フォルトになります。 use Inline C; greet('Ingy'); greet(42); __END__ __C__ void greet(SV* sv_name) { printf("Hello %s!\n", SvPVX(sv_name)); } =head2 例 #3 - 問題の修正 代わりにC関数を使うことにより、例#2での問題を修正することができます。この関数は、それに文字列が含まれていなければ、Cを文字列化します。Cはその2番目のパラメータとして、文字列の長さを返します。私たちは長さについて気にしていないので、そこにCを置くだけにすることができます。それはその目的のための特別な変数です。 use Inline C; greet('Ingy'); greet(42); __END__ __C__ void greet(SV* sv_name) { printf("Hello %s!\n", SvPV(sv_name, PL_na)); } =head1 参考資料 Inlineについての一般的な情報についてはLをご覧ください。 CでInlineを使ったサンプル・プログラムについてはLを、ご覧ください。 サポートされている言語とプラットホームについてはLをご覧くださ。い。 独自のInline言語サポート・モジュールを書くための情報についてはLをご覧ください。 Inlineのメーリングリストはinline@perl.orgです。 参加するためには、inline-subscribe@perl.orgにメールしてください。 =head1 バグと欠陥 =over 4 =item 1 Cの関数名に、たまたまPerlによって内部的に使われているものを使うと、実行時にロードエラーになります。現在のところこれを防いだり、警告する機能はありません。今はPerlの内部シンボルがファイル名C<'symbols.perl'>で、Inlineモジュール・ディストリビューションに入っています。コードではこれらを使わないようにしてください。 =back =head1 作者(AUTHOR) Brian Ingerson =head1 著作権(COPYRIGHT) Copyright (c) 2000, 2001. Brian Ingerson. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See http://www.perl.com/perl/misc/Artistic.html =head1 翻訳者 川合孝典 =cut