⭐如何在PHP扩展里面定义自己的类
使用php扩展实现一个getter setter 类
<?php
class Conn
{
protected string $host;
protected string $pass;
protected int $port;
public function __construct(string $host, string $pass, int $port)
{
$this->host = $host;
$this->pass = $pass;
$this->port = $port;
}
/**
* @param string $host
*/
public function setHost(string $host): void
{
$this->host = $host;
}
/**
* @param string $pass
*/
public function setPass(string $pass): void
{
$this->pass = $pass;
}
/**
* @param int $port
*/
public function setPort(int $port): void
{
$this->port = $port;
}
/**
* @return string
*/
public function getHost(): string
{
return $this->host;
}
/**
* @return string
*/
public function getPass(): string
{
return $this->pass;
}
/**
* @return int
*/
public function getPort(): int
{
return $this->port;
}
}
注册扩展模块入口
zend_module_entry example_module_entry = {
STANDARD_MODULE_HEADER,
"example", /* Extension name */
example_functions, /* zend_function_entry */
PHP_MINIT(example), /* PHP_MINIT - Module initialization (priority 1)*/
PHP_MSHUTDOWN(example), /* PHP_MSHUTDOWN - Module shutdown (priority 5)*/
PHP_RINIT(example), /* PHP_RINIT - Request initialization (priority 2)*/
PHP_RSHUTDOWN(example), /* PHP_RSHUTDOWN - Request shutdown (priority 4)*/
PHP_MINFO(example), /* PHP_MINFO - Module info (priority 3)*/
PHP_EXAMPLE_VERSION, /* Version */
STANDARD_MODULE_PROPERTIES
};
全局变量定义
zend_class_entry *zend_conn_ce;
类方法定义
static const zend_function_entry conn_functions[] = {
ZEND_ME(conn, __construct, arginfo_conn___construct, ZEND_ACC_PUBLIC)
ZEND_ME(conn, setHost, arginfo_conn_setHost, ZEND_ACC_PUBLIC)
ZEND_ME(conn, setPass, arginfo_conn_setPass, ZEND_ACC_PUBLIC)
ZEND_ME(conn, setPort, arginfo_conn_setPort, ZEND_ACC_PUBLIC)
ZEND_ME(conn, getHost, NULL, ZEND_ACC_PUBLIC)
ZEND_ME(conn, getPass, NULL, ZEND_ACC_PUBLIC)
ZEND_ME(conn, getPort, NULL, ZEND_ACC_PUBLIC)
ZEND_FE_END
};
方法参数注册
ZEND_BEGIN_ARG_INFO_EX(arginfo_conn___construct, 0, 0, 0)
ZEND_ARG_INFO(0, host)
ZEND_ARG_INFO(0, pass)
ZEND_ARG_INFO(0, port)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_conn_setHost, 0, 0, 0)
ZEND_ARG_INFO(0, host)
ZEND_END_ARG_INFO();
ZEND_BEGIN_ARG_INFO_EX(arginfo_conn_setPass, 0, 0, 0)
ZEND_ARG_INFO(0, pass)
ZEND_END_ARG_INFO();
ZEND_BEGIN_ARG_INFO_EX(arginfo_conn_setPort, 0, 0, 0)
ZEND_ARG_INFO(0, port)
ZEND_END_ARG_INFO();
getter无参数,无需定义,传入NULL占位即可
方法实现
ZEND_METHOD(conn, __construct)
{
zend_string *host = NULL;
zend_string *pass = NULL;
zend_long port = 0;
zval *object, tmp;
object = ZEND_THIS;
int argc = ZEND_NUM_ARGS(); //获取参数个数
//解析失败抛出异常
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc, "SSl", &host, &pass, &port) == FAILURE) {
zend_class_entry *ce;
if (Z_TYPE(EX(This)) == IS_OBJECT) {
ce = Z_OBJCE(EX(This));
} else if (Z_CE(EX(This))) {
ce = Z_CE(EX(This));
} else {
ce = object;
}
zend_throw_error(NULL, "Wrong parameters for %s([string $host [, string $pass [, int $port]]])", ZSTR_VAL(ce->name));
return;
}
if (host){
ZVAL_STR(&tmp, host);
zend_update_property_ex(zend_conn_ce, object, ZSTR_KNOWN(ZEND_STR_HOST), &tmp);
}
if (pass){
ZVAL_STR(&tmp, pass);
zend_update_property_ex(zend_conn_ce, object, ZSTR_KNOWN(ZEND_STR_PASS), &tmp);
}
if (port){
ZVAL_LONG(&tmp, port);
zend_update_property_ex(zend_conn_ce, object, ZSTR_KNOWN(ZEND_STR_PORT), &tmp);
}
}
ZEND_METHOD(conn, setHost)
{
zend_string *host;
zval tmp;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &host) == FAILURE) {
RETURN_FALSE;
}
ZVAL_STR(&tmp, host);
zend_update_property_ex(zend_conn_ce, getThis(), ZSTR_KNOWN(ZEND_STR_HOST), &tmp);
RETURN_TRUE;
}
ZEND_METHOD(conn, setPass)
{
zend_string *pass;
zval tmp;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &pass) == FAILURE) {
RETURN_FALSE;
}
ZVAL_STR(&tmp, pass);
zend_update_property_ex(zend_conn_ce, getThis(), ZSTR_KNOWN(ZEND_STR_HOST), &tmp);
RETURN_TRUE;
}
ZEND_METHOD(conn, setPort)
{
zend_long port;
zval tmp;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &port) == FAILURE) {
RETURN_FALSE;
}
ZVAL_LONG(&tmp, port);
zend_update_property_ex(zend_conn_ce, getThis(), ZSTR_KNOWN(ZEND_STR_PORT), &tmp);
RETURN_TRUE;
}
ZEND_METHOD(conn, getHost)
{
zval *prop, rv;
if (zend_parse_parameters_none() == FAILURE) {
return;
}
prop = zend_read_property_ex(zend_conn_ce, getThis(), ZSTR_KNOWN(ZEND_STR_HOST), 0, &rv);
ZVAL_DEREF(prop);
ZVAL_COPY(return_value, prop);
}
ZEND_METHOD(conn, getPass)
{
zval *prop, rv;
if (zend_parse_parameters_none() == FAILURE) {
return;
}
prop = zend_read_property_ex(zend_conn_ce, getThis(), ZSTR_KNOWN(ZEND_STR_PASS), 0, &rv);
ZVAL_DEREF(prop);
ZVAL_COPY(return_value, prop);
}
ZEND_METHOD(conn, getPort)
{
zval *prop, rv;
if (zend_parse_parameters_none() == FAILURE) {
return;
}
prop = zend_read_property_ex(zend_conn_ce, getThis(), ZSTR_KNOWN(ZEND_STR_PORT), 0, &rv);
ZVAL_DEREF(prop);
ZVAL_COPY(return_value, prop);
}
zend_parse_parameters_ex(flags, num_args, format, …)用来解析方法参数
- flags:
-
- ZEND_PARSE_PARAMS_QUIET
-
- ZEND_PARSE_PARAMS_THROW
- num_args: 参数个数
-
format:参数类型
-
- b: Boolean
-
- d: Double
-
- f: Float
-
- h: Resource handle
-
- l: Integer
-
- L: Long integer
-
- O: Object
-
- s: String
-
- a: Array
-
- A: Associative array
-
- z: Callable function
在PHP_MINIT方法内注册对象
PHP_MINIT_FUNCTION (example) {
zend_class_entry conn_ce;
INIT_CLASS_ENTRY(conn_ce, "Lackoxygen\\Conn", conn_functions); //初始化结构 如不需要命名空间只需填写类名
zend_conn_ce = zend_register_internal_class_ex(&conn_ce, NULL);//注册类
zend_declare_property_string(zend_conn_ce, "host", sizeof("host")-1, "", ZEND_ACC_PROTECTED);//注册属性protected string host
zend_declare_property_string(zend_conn_ce, "pass", sizeof("pass")-1, "", ZEND_ACC_PROTECTED);//注册属性protected string pass
zend_declare_property_long(zend_conn_ce, "port", sizeof("port")-1, NULL, ZEND_ACC_PROTECTED);//注册属性protected int port
return SUCCESS;
}
安装并测试
phpize
./configure
make && make install
echo extension=example >> php.ini
$conn = new \Lackoxygen\Conn('127.0.0.1', '123456', 6379);
$conn->setHost('192.168.0.1');
$conn->setPass('admin');
$conn->setPort(3306);
echo $conn->getHost() . "\n";
echo $conn->getPass() . "\n";
echo $conn->getPort() . "\n";