SHOEISHA iD

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

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

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

PHPエクステンションでクラスを作成する

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

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

コンストラクタの定義

 続いて、コンストラクタの実装を行います。

コンストラクタの実装(pzip_file.cの一部)
static zend_object_value php_pzip_file_new(zend_class_entry *ce TSRMLS_DC){
  zend_object_value retval;
  php_pzip_file *obj;

  obj = (php_pzip_file *)ecalloc(1,sizeof(php_pzip_file));   // ……(1)
  zend_object_std_init( &obj->std, ce TSRMLS_CC);            // ……(2)
  object_properties_init(&obj->std, ce);                     // ……(3)

  retval.handle = zend_objects_store_put(obj,
    (zend_objects_store_dtor_t) zend_objects_destroy_object,
    (zend_objects_free_object_storage_t) php_pzip_file_dtor, // ……(4)
    NULL TSRMLS_CC
  );
  retval.handlers = zend_get_std_object_handlers();          // ……(5)
  return retval;
}

 (1)で構造体のメモリ確保を行います。続いて、(2)ではPHPエンジン側でも必要な全体の初期化を行います。(3)ではPHP側に参照させるためのプロパティ情報の初期化をします。今回はPHP側で参照できるプロパティを定義していませんので、あまり関係がない処理ではありますが、今後プロパティを追加した場合に必要となる処理です。

 また、(4)では先ほど実装したデストラクタと一緒にオブジェクトデータをPHPエンジン側に登録します。(5)ではPHPエンジン側で使用するオブジェクト操作をするための関数を設定します。このように、クラスごとに異なる部分は、構造体の変数名程度でその他に異なる処理はありません。

コンストラクタの登録

 コンストラクタを定義したら、その関数をPHP_MINIT_FUNCTIONで登録する必要があります。

コンストラクタの登録(pzip_file.cの一部)
PHP_MINIT_FUNCTION(pzip_file){
  // : 省略
  pzip_file_ce = zend_register_internal_class(&ce TSRMLS_CC);
  pzip_file_ce->create_object = php_pzip_file_new;    // ……(1)
  return SUCCESS;
}

 そのために、(1)の行を追加する必要があります。

メソッドの定義

 続いて、メソッドの定義を行います。

$thisへのアクセス

 メソッドを定義する際には、必要なプロパティは$thisを通してPHPではアクセスができます。エクステンション内での$thisに相当する変数にアクセスするマクロが用意されています。

構造体を取得する方法(pzip_entry.cの一部)
//  $thisを取得する
php_pzip_entry *object = (php_pzip_entry *)
  zend_object_store_get_object(       // ……(1)
      getThis() TSRMLS_CC);           // ……(2)

 (2)のgetThis()が$thisに相当します。実際には関数の引数として渡ってくる変数を参照しています。次にこのgetThis()を引数として(1)zend_object_store_get_object()を使用して作成した構造体を取得します。

プロパティデータへの値の設定

 先ほど取得した構造体に値を設定してみます。まずは、単純に与えられた引数の文字列をそのまま保存するという実装をしてみます。以下のように使われる想定です。

phpでの実行例
$entry->setFilename("hello.png");

 注意すべき点が2つほどあります。実際にコードを示してみます。

構造体に値を設定する方法(pzip_entry.cの一部)
PHP_METHOD(PZipEntry, setFilename){
  const char *filename;
  int filename_len;
  //  : (省略)
  //  $thisを取得する
  php_pzip_entry *object = (php_pzip_entry *)
      zend_object_store_get_object(getThis() TSRMLS_CC);
  if(object->filename){
    efree(object->filename);            // ……(1)
  }
  object->filename = estrndup(filename,filename_len);  // ……(2)
  object->filename_length = filename_len;
  RETURN_TRUE;
}

 (1)は、すでに値が設定している場合の処理です。ここでメモリを解放しないとメモリリークが発生します。もちろん、メモリの解放方法は取得時の方法にもよりますが、ここでは(2)estrndupを使用し、文字列データを新たなメモリとして取得しコピーをしています。これはfilenameという変数はこの関数内でのスコープになるので、この変数の内容をコピーして再設定するという処理が必要になります。C言語に慣れている方でしたらこのあたりはあまり注意がいらないとは思いますが、PHPに慣れていると間違いやすいので注意が必要です。

プロパティデータからの値の取得

 プロパティへの値の設定方法が分かれば、ほぼ同様にして取得方法も分かると思いますが、念のために示しておきます。また、PHPからは以下のように使われる想定です。

phpでの実行例
$entry->getFilename();

 このように構造体が取得出来れば、あとは通常の関数を作成する際とまったく同じ方法で実装が可能です。

構造体から値を取得する方法(pzip_entry.cの一部)
PHP_METHOD(PZipEntry, getFilename){
  //  $thisを取得する
  //  : 省略
  if(object->filename){
    RETURN_STRINGL(object->filename,object->filename_length,1);
  }
  else{
    RETURN_NULL();
  }
}

最後に

 今回はまだクラスの作成方法の流れのみでしたが、できるだけ実用的な例をイメージして紹介しました。私の個人的な好みも含みますが、やはりPHPのエクステンションを作る際にクラスが作れると、関数名の重複を避けるための長い関数名を作成する必要もありません。また、一時的なデータ保存を構造体として共有できるので、PHP側とのデータのやりとりも、手軽に少なくできます。

 次回からは今回作成した例を拡張し、パスワード付きZipデータの解凍を行えるようにしていきます。外部ライブラリも使用していきますので、いよいよ実用的なエクステンションが作れるようになっていきます。

参考資料

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

  • 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/7441 2013/10/28 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

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

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

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

メールバックナンバー

アクセスランキング

アクセスランキング