PHP 拡張機能で PDO MySQL を使用したいのですが (PHP の単純な pdo ラッパー クラスではなく、C 言語を使用します)、このケースについてはわかりません。誰か助けてください。ありがとう。
1 に答える
私の問題はGoogleによって解決されました。このガイドに従って問題を解決できます。他のzendクラスで使用できます。
注: c で php 拡張機能を作成する方法に関する基本的な概念が必要です。
1.オリジンの zend_call_method にパッチを適用する必要があります。これは、オリジンの zend_call_method がサポートする引数は 3 つ未満であり、PDO のコンストラクターは 1 ~ 4 個の引数を使用するためです。
PDO::__construct() ( string $dsn [, string $username [, string $password [, array $driver_options ]]] )
PHPソースディレクトリ(おそらく「php-5.xx-src\Zend\zend_interfaces.c」)で「zend_interfaces.c」を見つけ、「zend_call_method」部分をターゲットにして、コードにコピーして貼り付け、次のようにします。
/* {{{ zend_call_method Only returns the returned zval if retval_ptr != NULL */ ZEND_API zval* zend_call_method_n_params( zval **object_pp, zend_class_entry *obj_ce, zend_function **fn_proxy, const char *function_name, int function_name_len, zval **retval_ptr_ptr, int param_count, zval *** params TSRMLS_DC) // ↑↑↑new function definition // only change "zval* arg1, zval* arg2" to "zval *** params" // make a new function name "zend_call_method_n_params" { ... //zval **params[2]; ← delete it! //params[0] = &arg1; ← delete it! //params[1] = &arg2; ← delete it! done. ... } /* }}} */
注: いくつかのマクロが必要になる場合があります。
#define call_method(obj, obj_ce, fn_proxy, function_name, retval, param_count, params) \
zend_call_method_n_params(obj, obj_ce, fn_proxy, function_name, sizeof(function_name)-1, retval, param_count, params TSRMLS_CC)
#define call_function(function_name, retval, param_count, params) \
zend_call_method(NULL, NULL, NULL, function_name, retval, param_count, params)
#define call_construct(obj, obj_ce, param_count, params) \
call_method(obj, obj_ce, &obj_ce->constructor, obj_ce->constructor->common.function_name, NULL, param_count, params)
2.ハローワールド!
コードをセットアップします。プロパティ「pdo」が必要です
PHP_MINIT_FUNCTION(yourextension)
{
...
zend_declare_property_null(you_class_entry, ZEND_STRL("pdo"),
ZEND_ACC_PUBLIC TSRMLS_CC);
...
}
PHP_METHOD(foo, bar) { char * dsn = "mysql:dbname=yourdb;host=127.0.0.1;port=3306"; char * usr = "username"; char * pwd = "password"; zval * zdsn = NULL; zval * zusr = NULL; zval * zpwd = NULL; zval ** params[3]; zend_class_entry * pdo_class_entry; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) { RETURN_FALSE; } // get class entry for PDO pdo_class_entry = zend_fetch_class(ZEND_STRL("PDO"), ZEND_FETCH_CLASS_AUTO TSRMLS_CC); // initial PDO instance MAKE_STD_ZVAL(pdo_inst); object_init_ex(pdo_inst, pdo_class_entry); // arg1: dns string ALLOC_INIT_ZVAL(zdns); ZVAL_STRINGL(zdsn, dsn, sizeof(dsn)-1, 1); // arg2: username ALLOC_INIT_ZVAL(zusr); ZVAL_STRINGL(zusr, usr, sizeof(usr)-1, 1); // arg3: password ALLOC_INIT_ZVAL(zpwd); ZVAL_STRINGL(zpwd, pwd, sizeof(pwd)-1, 1); // put them in params array params[0] = &zdsn; params[1] = &zusr; params[2] = &zpwd; // call PDO::__construct(zdns, zusr, zpwd) zend_call_method_n_params(&pdo_inst, pdo_class_entry, &pdo_class_entry->constructor, ZEND_STRL(pdo_class_entry->constructor->common.function_name), NULL, 3, // 3 params params TSRMLS_CC); // or simply use macro instead() //call_construct(&pdo_inst, pdo_class_entry,3,params); if (pdo_inst && Z_TYPE_P(pdo_inst) == IS_OBJECT) { zend_update_property(your_class_entry, getThis(), ZEND_STRL("pdo") , pdo_inst TSRMLS_CC); zend_printf("Success.\n"); } else { zend_printf("Failure.\n"); } }
PHP では、次のように呼び出すことができます。
$foo = new foo();
$foo->bar(); // connect by PDO and update $foo->pdo
// you can use pdo property now
var_dump($foo->pdo->query("select * from table")->fetchAll());
それは正常に動作します。乾杯!