C の構造体を扱うときには、XS の型に `T_PTROBJ' か `T_PRTREF'
を選択する必要があります。どちらの型も複雑なオブジェクトへのポインタを扱
うように設計されています。T_PTRREF 型では、Perl のオブジェクトが
bless
されていなくてもよいが、T_PTROBJ 型では、オブジェクトが
bless
されていなければなりません。T_PTROBJ を使うことで、XSUB は
Perl オブジェクトが期待する型であることを確認するようになりますから、型
チェックを行なうことができます。
次の XS コードでは、 getnetconfigent()
関数を ONC TIRPC といっしょ
に使っています。 getnetconfigent()
関数は、C の構造体へのポインタ
を返すもので、以下のプロトタイプで示されるものです。この例では、C のポイ
ンタを Perl のリファレンスにする方法を示すことにします。Perl は、このリ
ファレンスを bless されたオブジェクトへのポインタとみなして、このオブジェ
クトに対してデストラクタを起動しようとします。デストラクタは、
getnetconfigent()
が使ったメモリを解放するために、XS ソース内で記
述しす。XS でのデストラクタは、DESTROY で終わる名前を持つ XSUB 関数を記
述することで作ることができます。XS デストラクタは、別の XSUB が
malloc
したメモリを、 free
するために使うことができます。
struct netconfig *getnetconfigent(const char *netid);
struct netconfig
のために typedef
を行なっています。Perlの
オブジェクトは、C での型の名前に Ptr
というタグを付けたものにマッ
チする名前のクラスで bless
され、その名前は、Perl のパッケージ名
として使われるときには、空白を入れません。デストラクタは、そのオブジェク
トの属するクラスに対応するクラスに置かれ、Perl 側では DESTROY
と
いう名前で参照されますので、PREFIX
キーワードを使用して関数名の先
頭部分をみないようにします。
typedef struct netconfig Netconfig; MODULE = RPC PACKAGE = RPC Netconfig * getnetconfigent(netid) char * netid MODULE = RPC PACKAGE = NetconfigPtr PREFIX = rpcb_ void rpcb_DESTROY(netconf) Netconfig * netconf CODE: printf("Now in NetconfigPtr::DESTROY\n"); free( netconf );
この例には、次のような typemap
のエントリが必要になります。
拡張に際して、新しい typemap
を設けるときには、 @xref{typemap}, の節
の情報も参考にしてください。
TYPEMAP Netconfig * T_PTROBJ
今回の例は、
use RPC; $netconf = getnetconfigent("udp");
という Perl の文で使用されます。
Perl は $netconf で参照されるオブジェクトを消去するとき、そのオブ
ジェクトを用意された XSUB DESTROY 関数に送ります。Perl では、このオブジェ
クトが C の構造体であって、Perl のオブジェクトではないと知るすべがありま
せんし、関与もしません。この意味で、 getnetconfigent()
XSUB で作
られたオブジェクトと、普通の Perl のサブルーティンで作られたオブジェクト
の区別はありません。
Go to the first, previous, next, last section, table of contents.