SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

PHPエクステンションの作り方

PHPエクステンションで基本的な関数を作成する

PHPエクステンションの作り方 第2回

  • X ポスト
  • このエントリーをはてなブックマークに追加

基本的な型での扱いについて

 まずは、数値や文字列、BOOL値の扱い方を紹介します。これらの型がPHP上の最も基本的な型となり、これらの型を利用した基本的な関数の作成を示します。

PHPの型とエクステンション側の型について

 PHP側の型とエクステンション側の型は完全に一致しているわけではありません。特に、数値の場合には注意が必要になります。

 以下の関数は入力された数値(int型)をそのまま、戻り値として返す関数です。

数値(整数)を返す関数
PHP_FUNCTION(hellofunc_int){
    long arg_num;
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &arg_num) == FAILURE ){
        return;
    }
    RETURN_LONG(arg_num);
}

 今回も同様にPHPで記述した場合を示します。

PHPで定義した場合
function hellofunc_int($val){
    return $val;
}

 しかし、正確にはPHPで定義した関数とエクステンションとして定義した関数は異なる動作をします。PHPでは数値という漠然とした型で扱えます。実際にはint型やfloat型として扱われますが、それらは自動的にPHP側で制御してしまっています。ただし、C言語側ではそれをdouble型かlong型として認識させる必要があります。PHPでのint型はC言語側ではlongとして扱い、小数点などを含む数値のfloat型はC言語側ではdouble型として扱い処理をします。

double型として数値を扱う場合
PHP_FUNCTION(hellofunc_double){
    double arg_num;
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &arg_num) == FAILURE ){
        return;
    }
    RETURN_DOUBLE(arg_num);
}

 PHPは型を問わない言語ではありますが、実際には、文字列型、整数型、浮動小数点型、BOOL型、配列、null型、オブジェクト、リソースなどがあります。これらに応じて、引数からの値の変換方法や、戻り値の指定方法があります。

引数の取得方法

 引数を取得する場合には、zend_parse_parameters()関数を使います。この関数はPHPで引数を取得する場合に非常に便利な機能を提供してくれる関数で、データの変換を行ってくれます。実際に利用するには第1引数に実行時の引数の数、第2引数に型の指定を記述し、第3引数以降に実際に取得する変数を指定します。第3以降の変数は取得する型によって引数の数も種類も違います。また、TSRMLS_CCというマクロは、PHPをマルチスレッドとして動作させる時に有効になるマクロです。

 以下に、よく利用する型のサンプルと一覧を示します。

zend_parse_parametersの使用例
// BOOL型
zend_bool b;
zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b" , &b);
// 文字列型
char *arg = NULL;
int arg_len;
zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s" , &arg, &arg_len);
// 数値(long)型
long arg_num;
zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &arg_num);

 このように、型ごとに引数の数も変わってきます。

zend_parse_parametersのパラメータと引数の型
指定文字(第2引数) タイプ 代入数変数の型(第3引数以降)
a array zval*
b boolean zend_bool
d double double
f function zend_fcall_info*, zend_fcall_info_cache*
h array HashTable*
l long long
o objects zval*
O object(class定義したとき) zval*,zend_class_entry*
r resource char*
z mixed zval*

 これ以外にも、PHPのマニュアルを参照することで、そのすべてが分かります。

戻り値の設定方法

 関数の戻り値であるretrun_valueの正体は、zvalという構造体です。このzval構造体がPHPでいうmixed形式を実現しており、Zend/zend.hにその定義が記されています。

Zend/zend.hの抜粋
typedef struct _zval_struct zval;
struct _zval_struct {
    /* Variable information */
    zvalue_value value;             /* value */
    zend_uint refcount__gc;
    zend_uchar type;        /* active type */
    zend_uchar is_ref__gc;
};

 このように、値(zvalue_value)と型(type)をもった構造体となっています。また、値にはさまざまな型としてアクセスできるように、以下のような定義となっています。

Zend/zend.hの抜粋
typedef union _zvalue_value {
    long lval;    /* long value */
    double dval;  /* double value */
    struct {
        char *val;
        int len;
    } str;
    HashTable *ht;  /* hash table value */
    zend_object_value obj;
} zvalue_value;

 このあたりは前述したRETURN_STRINGLのマクロ展開からも推測ができると思います。関数からの戻り値を設定する場合に、時にはこれらについて詳しく知る必要がある場合もありますが、通常は以下のマクロを使用します。

戻り値の型と利用するマクロの一覧
戻り値の型 使用するマクロ 備考
NULL RETURN_NULL()  
BOOL RETURN_BOOL(int b)  
BOOL RETURN_TRUE RETURN_BOOL(1)と同様
BOOL RETURN_FALSE RETURN_BOOL(0)と同様
文字列 RETURN_STRING(char *s, int dup) 指定した文字列を返す
文字列 RETURN_STRINGL(char *s, int l, int dup) 指定した長さの文字列を返す
文字列 RETURN_EMPTY_STRING( ) 空文字を返す
数値(long) RETURN_LONG(long l)  
数値(double) RETURN_DOUBLE(double d)  

 また、戻り値を設定するマクロには、RETVAL_BOOL(int b)のように上記表に対応するRETURN_*ではなく、RETVAL_*のようなマクロも存在します。これは、RETURN_*マクロがreturnを行いそれ以降実行しないのに対して、RETVAL_*はそのまま処理を実行します。従って、メモリの解放など後処理を行いたい場合にはRETVAL_*を使う必要があります。

最後に

 今回は引数の扱い方と戻り値の基礎について扱いました。このような基本的な流れとルールが理解できると、既存のソースコードを読んだときに何となく意味が分かってくるのではないかと思います。また、これらの内容についてマニュアルで整備されている部分は少ないため、さまざまなサイトを参照し、情報を探すといったケースもあるかもしれません。しかし、必要な情報が載っているサイトというのは、あまり多くはないのです。そんなときは、PHPで既存の似た関数を探して、そのソースを参照するのがもっともよい方法です。

 次回は配列の引数や戻り値、そして、複数の引数を取る場合を説明し、より複雑な関数の作成方法について説明を行います。

参考資料

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
PHPエクステンションの作り方連載記事一覧

もっと読む

この記事の著者

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

WINGSプロジェクト 小林 昌弘(コバヤシ マサヒロ)

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/7328 2013/09/09 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング