在 windows 下 用C++ 开发 PHP 扩展

  我翻遍了Google, 也没用找到一篇真正能运行的C++ 下面 开发 PHP 扩展的文章。于是,我又翻遍了pecl,看看有没有例子。
发现还是没有。唯一能看到的几个是:Linux 下面 开发 C++ 扩展的文章,一试,发现时 php 5.0 beta 时候的文章了,都已经
过时了。无奈只能自己摸索。
  后来,在没有思路的时候,我觉得先编译PHP 开发包。结果,费了九牛二虎之力终于把 PHP 5.2 和  5.3 都在 visual stdio 下面编译
成功了。我编译了一个release 版本, 一个 debug 版本。release 版本 其实在 PHP 安装目录的 dev 下面有,如果不要debug 版本的,
可以直接用内置release,不需要编译 PHP 的开发包了。
  编译了PHP 之后,开始有些明白PHP 扩展 是怎么回事了。其实就是一个动态链接库。
  我通过 内置的 ext_skel_win32.php 生成一个扩展工程。当然,要做点改动,这个工程比较旧了,是对vc 6.0 的。
在 配置属性 ==》 c/c++ ==> 预处理定义  加一个 : _USE_32BIT_TIME_T 。这是 因为 vs 2005 用的是 64位的时间,
而zend 引擎默认是 32 位。
 在很多手册里面,都说要加  extern "c" {} 在头文件里面,实际上,根本就没有必要了,如果你只是些 5.2 以上的扩展的话。已经内部加好了。
这样,就能编译扩展了。记住,是release 版本的,如果要编译debug 版本的,那么就重新编译吧PHP吧。
  下面我说说 如何转换 C++ 的类,到 PHP。
比如 我有个 Dog 类,有个方法叫做 bark() 有个属性叫做 name(主意写法有很多种,我只是介绍一种)

 
zend_object_handlers dog_object_handlers;
zend_class_entry 
*dog_ce;

struct dog_object {
    zend_object std; 
// PHP 标准类
    Dog *dog; // dog 类
};

// 释放内存
void dog_free_storage(void *object TSRMLS_DC)
{
    dog_object 
*obj = (dog_object *)object;

    delete obj
->dog;

    zend_hash_destroy(obj
->std.properties);
    FREE_HASHTABLE(obj
->std.properties);

    efree(obj);
}

//  创建内置PHP 类,其实类就是一个 zend hash
zend_object_value dog_create_handler(zend_class_entry *type TSRMLS_DC)
{
    zval 
*tmp;
    zend_object_value retval;

    dog_object 
*obj = (dog_object *)emalloc(sizeof(dog_object));
    memset(obj, 
0sizeof(dog_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,
        dog_free_storage, NULL TSRMLS_CC);
    retval.handlers 
= &dog_object_handlers;

    
return retval;
}

PHP_METHOD(Dog, __construct)
{
    
string name;
    Dog 
*dog = NULL;
    zval 
*object = getThis();

    
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s"&name) == FAILURE) {
        RETURN_NULL();
    }

    dog 
= new Dog(name);
    dog_object 
*obj = (dog_object *)zend_object_store_get_object(object TSRMLS_CC);
    obj
->dog = dog;
}


PHP_METHOD(Dog, bark)
{
    Dog 
*dog;
    dog_object 
*obj = (dog_object *)zend_object_store_get_object(
        getThis() TSRMLS_CC);
    dog 
= obj->dog;
    
if (dog != NULL) {
        dog
->bark();
    }
}

function_entry dog_methods[] 
= {
    PHP_ME(Dog,  __construct,     NULL, ZEND_ACC_PUBLIC 
| ZEND_ACC_CTOR)
    PHP_ME(Dog,  bake,           NULL, ZEND_ACC_PUBLIC)
    {NULL, NULL, NULL}
};


PHP_MINIT_FUNCTION(cplusplusdog)
{
    zend_class_entry ce;
    INIT_CLASS_ENTRY(ce, 
"Dog", dog_methods);
    dog_ce 
= zend_register_internal_class(&ce TSRMLS_CC);
    dog_ce
->create_object = dog_create_handler;
    memcpy(
&dog_object_handlers,
        zend_get_std_object_handlers(), 
sizeof(zend_object_handlers));
    dog_object_handlers.clone_obj 
= NULL;
    
return SUCCESS;
}

好了,不罗嗦了,可以说,zend 2.2 已经非常的支持 C++ 写扩展了。c++的开发效率对我这样的菜鸟来说要比c快
很多。
posted @ 2009-08-15 11:47  暮夏  阅读(1850)  评论(2编辑  收藏  举报