Go to the first, previous, next, last section, table of contents.


Perl のオブジェクトと C の構造体

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.

検索式: