1.在建立好最简单的扩展后,发现不能用C++的东西在C文件里。于是在原生成的文件上添加了MyCPP.cpp ,将自定义的函数,添加动这个.cpp里。头文件要用extern "C" 包起。
extern "C"
{
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "php.h"
#include "php_ini.h"
#include "ext/standard/info.h"
#include "php_weftext.h"
}
2. 添加好简单的CPP类,及相关扩展函数,如下。然后编译发现产生错误:“std::endl”: 不允许 dllimport 函数 的定义 ... 。于是定义宏这个“_ALLOW_KEYWORD_MACROS”解决。
//用来测试便写的扩展是否正确运行
PHP_FUNCTION(mytestext_test_hello)
{
char *dd=new char[100];
char *arg = NULL;
int arg_len, len;
char *strg;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg, &arg_len) == FAILURE) {
return;
}
len = spprintf(&strg, 0, "The string you put in is : %s", arg);
RETURN_STRINGL(strg, len, 0);
}
#include <string>
extern "C"
{
zend_object_handlers mytestext_object_handlers;
zend_class_entry *mytestext_ce;
struct mytestext_object {
zend_object std; // PHP 标准类
CMyTestClass *mytestextobj; // mytestextobj 类
};
// 释放内存
void mytestext_free_storage(void *object TSRMLS_DC)
{
mytestext_object *obj = (mytestext_object *)object;
delete obj->mytestextobj;
zend_hash_destroy(obj->std.properties);
FREE_HASHTABLE(obj->std.properties);
efree(obj);
}
// 创建内置PHP 类,其实类就是一个 zend hash
zend_object_value mytestext_create_handler(zend_class_entry *type TSRMLS_DC)
{
zval *tmp;
zend_object_value retval;
mytestext_object *obj = (mytestext_object *)emalloc(sizeof(mytestext_object));
memset(obj, 0, sizeof(mytestext_object));
obj->std.ce = type;
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,
mytestext_free_storage, NULL TSRMLS_CC);
retval.handlers = &mytestext_object_handlers;
return retval;
}
PHP_METHOD(mytestext, __construct)
{
char *str = NULL;
int strlen = 0;
CMyTestClass *mytestextobj = NULL;
zval *object = getThis();
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str,&strlen) == FAILURE) {
RETURN_NULL();
}
mytestextobj = new CMyTestClass(/*string(str,strlen)*/);
mytestext_object *obj = (mytestext_object *)zend_object_store_get_object(object TSRMLS_CC);
obj->mytestextobj = mytestextobj;
}
PHP_METHOD(mytestext, bark)
{
CMyTestClass *mytestextobj;
mytestext_object *obj = (mytestext_object *)zend_object_store_get_object(
getThis() TSRMLS_CC);
mytestextobj = obj->mytestextobj;
if (mytestextobj != NULL) {
//mytestextobj->bark();
}
}
zend_function_entry mytestext_methods[] = {
PHP_ME(mytestext, __construct, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
//PHP_ME(mytestext, bake, NULL, ZEND_ACC_PUBLIC)
{NULL, NULL, NULL}
};
/* {{{ PHP_MINIT_FUNCTION
*/
PHP_MINIT_FUNCTION(mytestext)
{
/* If you have INI entries, uncomment these lines
REGISTER_INI_ENTRIES();
*/
zend_class_entry ce;
INIT_CLASS_ENTRY(ce, "mytestext", mytestext_methods);
mytestext_ce = zend_register_internal_class(&ce TSRMLS_CC);
mytestext_ce->create_object = mytestext_create_handler;
memcpy(&mytestext_object_handlers,
zend_get_std_object_handlers(), sizeof(zend_object_handlers));
mytestext_object_handlers.clone_obj = NULL;
return SUCCESS;
}
/* }}} */
}
3.再编译,表现还是不对。产生错误:error : The C++ Standard Library forbids macroizing keywords. Enable warning C4005 to find the forbidden macro.找到时错误原因是自定义了inline。于是将php source code 中所有的inline 变成 __inline ,同时将所有的#define inline 注释掉,这个问题目才得以解决(还好php source code 中用inline的地方不多)。
4.发现还不对,产生“_zend_new_interned_string”未定义错误。找了一会儿发现有个宏“LIBZEND_EXPORTS" ,去掉这个宏后,没出现这个错误了。
5.最后编译成功。然后希望下次用php source code 时php 自己把这些问题目改了。