SHOEISHA iD

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

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

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

PHPで外部ライブラリ(libzip)を組み込んで利用する

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

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

クラスのインスタンスを返す方法と引数として利用する方法

 続いて、クラスのインスタンスを返す方法や、引数として利用する方法を紹介します。クラスのインスタンスを返すことで、配列と同様に一度に多くのデータを戻すことができ、また配列とは違い、よりデータへのアクセス方法が管理されたデータをPHP側に戻すことができます。そして、引数にクラスのインスタンスを使えば、プリミティブな値と違ってPHPエンジニア側のタイプミスなどが起こりにくくなります。クラス構成でエクステンションを作成する場合には、ぜひ利用したいテクニックの一つです。

メソッドの中でクラスのインスタンスを返す

 PZipEntryクラスのインスタンスを返すメソッドを実装します。実際に実行される時のPHPのコードは、以下のようになります。

PHP側のコード:クラスのインスタンスを返すメソッド
$entry = $pzip_file->getEntry(0);

 また、クラスのインスタンスを返すエクステンション側の実装は以下のようになります。

クラスのインスタンスを返す(pzip_file.cの抜粋)
PHP_METHOD(PZipFile, getEntry){
    : // (省略)
    php_pzip_entry *entry;
    : // (省略)
    else{
        : // (省略)
        object_init_ex(return_value, pzip_entry_ce); // ……(1)
        
        Z_SET_REFCOUNT_P(return_value, 1);           // ……(2)
        Z_SET_ISREF_P(return_value);                 // ……(3)
        entry = (php_pzip_entry *)zend_object_store_get_object(return_value TSRMLS_CC); //……(4)
        entry->stat = stat;                          // ……(5)
    }
}

 (1)でPZipEntryのzend_class_entryである、pzip_entry_ceを指定し、インスタンスを初期化します。(2)(3)はインスタンスの参照カウンタを設定します。参照カウンタについては、http://www.php.net/manual/ja/features.gc.refcounting-basics.phpを参照すると詳しいことが分かります。(4)zend_object_store_get_objectでreturn_valueの変数から、クラスの内部データを管理するphp_pzip_entryの構造体を取得します。(5)では、その構造体に値を設定していきます。同様にほかの変数に値を設定することも可能です。

クラスのインスタンスを引数として利用する

 クラスのインスタンスを引数から取得するには、ほかと同様にzend_parse_parameters()を利用すればよいので、非常に簡単に取得できます。

クラスのインスタンスを引数から取得(pzip_file.cの抜粋)
PHP_METHOD(PZipFile, getStream){
    : // (省略)
    zval *z_entry;
    php_pzip_entry *entry;
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O",
                          &z_entry, pzip_entry_ce) == FAILURE ){  // ……(1)
        return;
    }
    entry = (php_pzip_entry *)zend_object_store_get_object(z_entry TSRMLS_CC); // ……(2)
    : // (省略)
    if(entry->stat->encryption_method){                           // ……(3)
        if(!obj->password){
            php_error_docref(NULL TSRMLS_CC, E_ERROR, "Please set password");
            RETURN_FALSE;
        }
        zf = zip_fopen_index_encrypted(obj->zip,entry->stat->index,flags,obj->password);   // ……(4)
    }
    else{
        zf = zip_fopen_index(obj->zip,entry->stat->index,flags);  // ……(5)
    }
    : // (省略)
}

 (1)zend_parse_parameters()の第1引数に"O"を指定し、第2引数には実際に値が設定されるzvalの変数、第3引数にはクラスの型を示すzend_class_entryの型であるpzip_entry_ce変数を設定します。そして、そのクラスの内部データ構造体の変数を取得するには、(2)zend_object_store_get_object()を利用します。このとき、引数として(1)で取得したzvalの値を引数に設定します。これで構造体にアクセスできたので、後はそれぞれの実装をしていくことが可能です。

 今回のサンプルでは、(3)のようにZIPのエントリーから暗号方式の情報を取得し、その状況に合わせて、(4)暗号解読方式でのZIPエントリデータのオープン、もしくは、(5)通常法方式でのZIPエントリデータのオープンをしています。

 以上でクラスのひな形としての実装は終了しました。ただし、実際にzip_fopen_index関数を通じて取得したリソースは、まだ扱うことができません。次回はそのリソースをPHPでのストリーム関数を通じてアクセスできるようにします。

最後に

 今回はlibzipというライブラリを組み込み、PHPで標準的に用意されているZipArchiveで足りない部分を補うことができるようにサンプルコードを紹介しました。実際のエクステンションの開発をゼロから行うことはなくても、既存のエクステンションに機能を追加することができれば、より利用シーンが広がると思います。

 また、PHPのメリットの一つに、ネイティブライブラリのブリッジモジュールを簡単に作れることがあります。今までコマンドラインなどを通じて、ネイティブライブラリを利用しているケースでは、そのライブラリをPHP自体に組み込むことで、コマンドラインなどで扱うよりも柔軟にそして軽量に構築が行えます。そして、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/7524 2013/12/20 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

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

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

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

メールバックナンバー

アクセスランキング

アクセスランキング