前言
本篇博文是对PHP扩展开发及内核应用第10-11章的学习、练习、总结。
练习习题
用php扩展实现
abstract class My_Yaf_Request_Abstract
{
protected $action;
public function __construct()
{
echo "I am My_Yaf_Request_Abstract\n";
}
public function setActionName($action_name)
{
$this->action = $action_name;
}
public function getActionName()
{
return $this->action;
}
public abstract function isCli();
}
class My_Yaf_Request_Http extends My_Yaf_Request_Abstract
{
public function __construct()
{
echo("I am My_Yaf_Request_Http\n");
}
public function isCli()
{
return false;
}
}
class My_Yaf_Request_Simple extends My_Yaf_Request_Abstract
{
public function __construct()
{
echo("I am My_Yaf_Request_Simple\n");
}
public function isCli()
{
return true;
}
}
实现
PHP扩展开发及内核应用中对类的实现已经讲得十分详细,直接贴上我的实现吧。
//myyaf.c
#include "myyaf.h"
//module entry
#ifdef COMPILE_DL_MYYAF
zend_class_entry *my_yaf_request_abstract;
zend_class_entry *my_yaf_request_http;
zend_class_entry *my_yaf_request_simple;
ZEND_METHOD(My_Yaf_Request_Abstract, __construct)
{
php_printf("I am My_Yaf_Request_Abstract\n");
}
ZEND_METHOD(My_Yaf_Request_Abstract, isCli)
{
}
ZEND_METHOD(My_Yaf_Request_Abstract, setActionName)
{
zval *action;
zend_class_entry *ce;
ce = Z_OBJCE_P(getThis());
if( zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &action) == FAILURE )
{
printf("Error\n");
RETURN_NULL();
}
zend_update_property(ce, getThis(), "action", sizeof("action")-1, action TSRMLS_CC);
}
ZEND_METHOD(My_Yaf_Request_Abstract, getActionName)
{
zval *action;
zend_class_entry *ce;
ce = Z_OBJCE_P(getThis());
action = zend_read_property(ce, getThis(), "action", sizeof("action")-1, 1 TSRMLS_DC);
RETVAL_ZVAL(action,1,0);
}
ZEND_METHOD(My_Yaf_Request_Http, __construct)
{
php_printf("I am My_Yaf_Request_Http\n");
}
ZEND_METHOD(My_Yaf_Request_Http, isCli)
{
RETVAL_BOOL(0);
}
ZEND_METHOD(My_Yaf_Request_Simple, __construct)
{
php_printf("I am My_Yaf_Request_Simple\n");
}
ZEND_METHOD(My_Yaf_Request_Simple, isCli)
{
RETVAL_BOOL(1);
}
static zend_function_entry my_yaf_request_abstract_method[] = {
ZEND_ME(My_Yaf_Request_Abstract, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
ZEND_ME(My_Yaf_Request_Abstract, getActionName, NULL, ZEND_ACC_PUBLIC)
ZEND_ME(My_Yaf_Request_Abstract, setActionName, NULL, ZEND_ACC_PUBLIC)
ZEND_ME(My_Yaf_Request_Abstract, isCli, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_ABSTRACT)
ZEND_ME(My_Yaf_Request_Abstract, isCli, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_ABSTRACT)
{NULL, NULL, NULL}
};
static zend_function_entry my_yaf_request_http_method[] = {
ZEND_ME(My_Yaf_Request_Http, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
ZEND_ME(My_Yaf_Request_Http, isCli, NULL, ZEND_ACC_PUBLIC)
{NULL, NULL, NULL}
};
static zend_function_entry my_yaf_request_simple_method[] = {
ZEND_ME(My_Yaf_Request_Simple, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
ZEND_ME(My_Yaf_Request_Simple, isCli, NULL, ZEND_ACC_PUBLIC)
{NULL, NULL, NULL}
};
ZEND_MINIT_FUNCTION(myyaf)
{
zend_class_entry ce, http_ce, simple_ce;
INIT_CLASS_ENTRY(ce, "My_Yaf_Request_Abstract", my_yaf_request_abstract_method);
my_yaf_request_abstract = zend_register_internal_class(&ce TSRMLS_CC);
zend_declare_property_null(my_yaf_request_abstract, "action", strlen("action"), ZEND_ACC_PROTECTED TSRMLS_CC);
INIT_CLASS_ENTRY(http_ce, "My_Yaf_Request_Http", my_yaf_request_http_method);
my_yaf_request_http = zend_register_internal_class_ex(&http_ce, my_yaf_request_abstract, "My_Yaf_Request_Abstract" TSRMLS_CC);
my_yaf_request_http->ce_flags |= ZEND_ACC_FINAL_CLASS;
INIT_CLASS_ENTRY(simple_ce, "My_Yaf_Request_Simple", my_yaf_request_simple_method);
my_yaf_request_simple = zend_register_internal_class_ex(&simple_ce, my_yaf_request_abstract, "My_Yaf_Request_Abstract" TSRMLS_CC);
my_yaf_request_simple->ce_flags |= ZEND_ACC_FINAL_CLASS;
return SUCCESS;
}
zend_module_entry myyaf_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
STANDARD_MODULE_HEADER,
#endif
"myyaf", //这个地方是扩展名称,往往我们会在这个地方使用一个宏。
NULL, /* Functions */
ZEND_MINIT(myyaf), /* MINIT */
NULL, /* MSHUTDOWN */
NULL, /* RINIT */
NULL, /* RSHUTDOWN */
NULL, /* MINFO */
#if ZEND_MODULE_API_NO >= 20010901
"2.1", //这个地方是我们扩展的版本
#endif
STANDARD_MODULE_PROPERTIES
};
ZEND_GET_MODULE(myyaf)
#endif
myyaf.h
//php_myyaf.h
#ifndef MYYAF_H
#define MYYAF_H
//加载config.h,如果配置了的话
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
//加载php头文件
#include "php.h"
#define phpext_myyaf_ptr &myyaf_module_entry
extern zend_module_entry myyaf_module_entry;
#endif
测试用例
<?php
$obj_http = new My_Yaf_Request_Http();
$obj_simple = new My_Yaf_Request_Simple();
$obj_http->setActionName("action_http");
var_dump($obj_http->getActionName());
$obj_http->setActionName("action_simple");
var_dump($obj_http->getActionName());
var_dump($obj_http->isCli());
var_dump($obj_simple->isCli());
存疑
5.4.33的zend引擎只显式提供了zend_register_internal_class
和zend_register_internal_class_ex
分别表示类和子类,并没有提供Abstract类的注册方法。关于如何注册Abstract类,这部分作为后续存疑查找。