VS2012 编译 PHP C++ 扩展奇遇

来源:互联网 发布:sftp端口登录命令 编辑:程序博客网 时间:2024/06/06 02:56

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 自己把这些问题目改了。



原创粉丝点击