PHP 也有 Day #21 從 C 語言到 PHP Extension 錄影
實作一個在 PHP 是這樣的一個類別
Class MyClass {
protected $name = "";
public function __construct($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
public function setName($name) {
$this->name = $name;
}
public function helloWorld() {
return "Hello World";
}
}
在 extension.c 寫完會如下
#include "php_myclass.h"
#if COMPILE_DL_MYCLASS
ZEND_GET_MODULE(myclass)
#endif
// 宣告一個 global zend_class_entry 變數
zend_class_entry *myclass_ce;
/*
這裡由原本的 PHP_FE 改用 PHP_ME
四個參數為
className:class PHP 呼叫的名字
methodName:method 呼叫的名字
arg_info:先帶 NULL,可以設定帶進來的參數值,可參考 http://www.walu.cc/phpbook/preface.md
flags:有以下參數 ZEND_ACC_PUBLIC, ZEND_ACC_PROTECTED, ZEND_ACC_PRIVATE, ZEND_ACC_STATIC, ZEND_ACC_FINAL, ZEND_ACC_ABSTRACT
分別表示 public , protected , private , static , final , abstract
如果要寫 abstract method 是使用 PHP_ABSTRACT_ME,就可以不用實作內容
下述就是定義 MyClass 這個類別
有 php 的 construct public funciton __construct
一般 method 有
public funciton getName
public funciton setName
public funciton helloWord
*/
static const zend_function_entry myclass_functions[] = {
PHP_ME(MyClass, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
PHP_ME(MyClass, getName, NULL, ZEND_ACC_PUBLIC)
PHP_ME(MyClass, setName, NULL, ZEND_ACC_PUBLIC)
PHP_ME(MyClass, helloWorld, NULL, ZEND_ACC_PUBLIC)
PHP_FE_END
};
/*
原本這裡的第三個參數改成 NULL,它原本是帶上面這個 zend_function_entry 的變數
第四個參數改成 PHP_MINIT(myclass)
class 改成要在 module init 這個周期宣告 class
Ref:http://www.walu.cc/phpbook/1.3.md
*/
zend_module_entry myclass_module_entry = {
STANDARD_MODULE_HEADER,
"myclass", // your extension name
NULL, // where you define your functions
PHP_MINIT(myclass), // for module initialization
NULL, // PHP_MSHUTDOWN(myclass), // for module shutdown process
NULL, // PHP_RINIT(myclass) // for request initialization
NULL, // PHP_RSHUTDOWN(myclass) // for reqeust shutdown process
NULL, // PHP_MINFO(myclass), // for providing module information
"0.1",
STANDARD_MODULE_PROPERTIES
};
/*
PHP_MINIT(myclass) 實作內容
註冊一個叫 MyClass 的類別
myclass_functions 也在這裡被使用
全域的 myclass_ce 內容在這裡實際取得
*/
PHP_MINIT_FUNCTION(myclass)
{
zend_class_entry tmp_ce;
INIT_CLASS_ENTRY(tmp_ce, "MyClass", myclass_functions);
myclass_ce = zend_register_internal_class(&tmp_ce TSRMLS_CC);
return SUCCESS;
}
/*
實作 __construct
大致跟之前寫 function 差不多
不過這裡有用 zend_update_property* 的 function
這一系列的都是用來設定 class property
全域的 myclass_ce 也在這裡被使用到,寫進 myclass_ce 的意思
這裡我用來設定
Class MyClass {
protected $name = "";
}
這個 name property
getThis() 是取得這個 class handle
Ref:http://www.walu.cc/phpbook/11.2.md
*/
PHP_METHOD(MyClass, __construct)
{
char *name = NULL;
int name_len;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|", &name, &name_len) == FAILURE) {
RETURN_NULL();
}
zend_update_property_stringl(myclass_ce, getThis(), "name", sizeof("name") - 1, name, name_len TSRMLS_CC);
}
/*
實作 getName
zend_parse_parameters_none 判斷不能傳參數進來
zend_read_property 取得 name 這個 property
Z_STRVAL_P 從 zval 取得 string
RETURN_STRING Return string
*/
PHP_METHOD(MyClass, getName)
{
zval *name = NULL;
if (zend_parse_parameters_none() == FAILURE) {
RETURN_FALSE;
}
name = zend_read_property(myclass_ce, getThis(), "name", sizeof("name") - 1, 1 TSRMLS_CC);
RETURN_STRING(Z_STRVAL_P(name), 1);
}
/*
實作 setName
*/
PHP_METHOD(MyClass, setName)
{
char *name = NULL;
int name_len;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|", &name, &name_len) == FAILURE) {
RETURN_NULL();
}
zend_update_property_stringl(myclass_ce, getThis(), "name", sizeof("name") - 1, name, name_len TSRMLS_CC);
}
/*
實作 helloWorld
*/
PHP_METHOD(MyClass, helloWorld)
{
if (zend_parse_parameters_none() == FAILURE) {
RETURN_FALSE;
}
RETURN_STRING("Hello World", 1);
}
沒有留言:
張貼留言