私はPHPの拡張機能を作成するこの分野では初めてですが、C++からPHPへのラッパークラスを作成する必要があります。私は現在PHP5.2.13を使用しています。この記事http://devzone.zend.com/article/4486-Wrapping-C-Classes-in-a-PHP-Extensionを読みました。これは、C++クラスをラップしてPHPZendと通信する方法に関するチュートリアルです。 Linuxシステム用に書き込まれます。PHPと通信するためのラッパークラスの作成に進む方法についての記事やアドバイスはありますか?
2 に答える
これはまさに私が最近やっていることです。あなたが参照したチュートリアルは良いものです (それは私の出発点でもありました)。クラスをラップするために私が従った基本的なプロセスは次のとおりです。次の名前の C++ クラスをラップしているとしますMyclass。
php_myclass.h を作成します。
#ifndef PHP_MYCLASS_H
#PHP_MYCLASS_H を定義
extern "C" {
#include "php.h"
}
// C++ クラス定義を含めます
#include "Myclass.h"
// これは、Myclass の PHP バージョンを表す構造体です。
// これには、Myclass へのポインタと PHP の zend_object が含まれているだけです。
struct myclass_object {
zend_object std;
Myclass *myclass;
};
// これは、ユーザー空間で呼び出される PHP クラス (PHP コード) です。
#define PHP_MYCLASS_CLASSNAME "Myclass"
extern zend_class_entry *myclass_ce;
extern zend_object_handlers myclass_object_handlers;
zend_object_value myclass_create_handler(zend_class_entry *type TSRMLS_DC);
// 後で、これは Myclass のメソッド宣言でいっぱいの配列になります
extern function_entry php_myclass_functions[];
#endif /* PHP_MYCLASS_H */
次に、 php_myclass.cppで php クラスを定義します。
#include "php_myclass.h"
zend_class_entry *myclass_ce;
zend_object_handlers myclass_object_handlers;
// 私はまだ初心者ですが、これはメモリ管理を処理する関数だと思います
// PHP クラスが削除されます (範囲外、スクリプト終了など)
void myclass_free_storage(void *object TSRMLS_DC)
{
myclass_object *obj = (myclass_object*)オブジェクト;
obj->myclass を削除します。
zend_hash_destroy(obj->std.properties);
FREE_HASHTABLE(obj->std.properties);
efree(obj);
}
// 同様に、名前が示すように、これはメモリ管理を処理すると思います
// Myclass がインスタンス化されたとき。
zend_object_value myclass_create_handler(zend_class_entry *type TSRMLS_DC)
{
zval *tmp;
zend_object_value retval;
// 新しい PHP Myclass オブジェクト用にメモリに空きを作ります:
myclass_object *obj = (myclass_object*)emalloc(sizeof(myclass_object));
// そのメモリを 0 で埋める
memset(obj, 0, sizeof(myclass_object));
obj->std.ce = タイプ;
// 魔法のようなもの (わかりません)
ALLOC_HASHTABLE(obj->std.properties);
zend_hash_init(obj->std.properties, 0, NULL, ZVAL_PTR_DTOR, 0);
zend_hash_copy(obj->std.properties, &type->default_properties, (copy_ctor_func_t)zval_add_ref, (void*)&tmp, sizeof(zval*));
// 後のコードでこのオブジェクトのインスタンスを取得できるようにします
retval.handle = zend_objects_store_put(obj, NULL, myclass_free_storage, NULL TSRMLS_CC);
retval.handlers = &myclass_object_handlers;
retval を返します。
}
// 最初に、引数を取るメソッドの引数情報を定義します (ある場合)。
// これは明らかに 1 つの引数を意味します:
ZEND_BEGIN_ARG_INFO_EX(php_myclass_one_arg, 0, 0, 1)
ZEND_END_ARG_INFO()
// この 1 つの 2 つの引数など
ZEND_BEGIN_ARG_INFO_EX(php_myclass_two_args, 0, 0, 2)
ZEND_END_ARG_INFO()
// ここで、Myclass PHP クラスが持つメソッドを PHP に伝えます。
function_entry php_myclass_functions[] = {
// この行の最後にあるコンストラクターの特別なプロパティ:
PHP_ME(Myclass,__construct,NULL,ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
// 通常のメソッドは次のようになります。
PHP_ME(Myclass,methodNameNoArgs,NULL,ZEND_ACC_PUBLIC)
PHP_ME(Myclass,methodName1Arg,php_myclass_one_arg,ZEND_ACC_PUBLIC)
PHP_ME(Myclass,methodName2Args,php_myclass_two_args,ZEND_ACC_PUBLIC)
// 3 つの魔法の NULL 値、なぜここに行かなければならないのかわかりません。
{ヌル、ヌル、ヌル}
};
// 次に、PHP に指示した Myclass メソッドをそれぞれ定義します
// ユーザー空間に公開する:
PHP_METHOD(Myclass, __construct)
{
マイクラス *マイクラス = NULL;
zval *object = getThis();
// ラップするクラスのインスタンスを作成します
myclass = 新しい Myclass();
// Make object (PHP オブジェクト インスタンスの $this を指します)
// PHP クラスを表す構造体のインスタンス
myclass_object *obj = (myclass_object*)zend_object_store_get_object(オブジェクト TSRMLS_CC);
// this の内部 Myclass を作成したばかりの Myclass のインスタンスに設定します
obj->myclass = myclass;
// 終わり。
}
PHP_METHOD(Myclass, methodNameNoArgs)
{
// PHP Myclass の現在のインスタンスを myclass に取得します。
Myclass *myclass;
myclass_object *mo = (myclass_object*)zend_object_store_get_object(getThis() TSRMLS_CC);\
myclass = mo->myclass;
if (obj == NULL) {
// エラーチェック
RETURN_NULL();
}
// RETURN_* マクロの 1 つを使用して myclass メソッドの値を返します
// ここでは、これがブール値を返すふりをします:
RETURN_BOOL(myclass->methodNameNoArgs());
}
PHP_METHOD(Myclass, methodName1Arg)
{
// ここで、Myclass::methodName1Arg(int) が int を取るふりをしましょう
// std::vector を返します (これを配列にしたい)
長いパラメータ;
// PHP Myclass の現在のインスタンスを myclass に取得します。
Myclass *myclass;
myclass_object *mo = (myclass_object*)zend_object_store_get_object(getThis() TSRMLS_CC);\
myclass = mo->myclass;
if (obj == NULL) {
// エラーチェック
RETURN_NULL();
}
// PHP メソッド呼び出しのパラメーターを解析する方法は次のとおりです。
// 2 番目のパラメーターは long int の "l" です。詳細については、オンラインのチュートリアルを参照してください
// この関数の使用方法について。
if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", ¶m) == FAILURE) {
RETURN_NULL();
}
// PHP 用に変換したい実際の戻り値を取得します
std::vector retval = myclass->methodName1Arg(param);
// 魔法の "return_value" を使用します (これは舞台裏ですべてのメソッドにあります)
// PHP 配列になるように初期化します。
array_init(戻り値);
// ベクトルをループして配列を構築します。
for (std::vector::iterator i = retval.begin(); i != retval.end(); ++i) {
add_next_index_long(return_value, *i);
}
// 終わり。return_value は常に返されます。
}
PHP_METHOD(Myclass, methodName2Args)
{
// 「Left as a practice for the reader」はコーダー スラングです。
// 「私は *本当に* もうタイピングしたくありません。」:)
}
このサンプル コードがコンパイルされるか、少なくとも役立つことを願っています。:) それは、私がここに持っている実際の作業コードから急いでまとめられたものであり、検索/置換が何かを壊した場合、少なくとも何をすべきかについてのアイデアが得られるかもしれません. これには省略されていることがたくさんあります。詳細については、 http: //devzone.zend.com/article/1021 にある Sara Golemon の 3 部構成の拡張チュートリアルをお読みください。幸運を。
あなたが見つける最良の「ドキュメント」は、PHP のソースコードと拡張機能です (申し訳ありません)。重要なことを行うとすぐに、ソース (特に Zend エンジンのヘッダー) を掘り下げる必要があることに気付くでしょう。
そうは言っても、始めるのに役立つリソースがいくつかあります。これらの記事とSara Golemon による PHP の拡張と埋め込みを参照してください。pecl.php.net/support.php も参照してください。