资源类型

资源类型

1,创建一个扩展

./ext_skel --extname=resource

2,操作函数

/*resource类型在内核中的定义*/   
typedef struct _zend_rsrc_list_entry {
    void *ptr;
    int type;
    int refcount;
} zend_rsrc_list_entry;

/*添加分类
    zend_register_list_destructors  => 没有类别名, resource(4) of type (Unknown)
    zend_register_list_destructors_ex => 有类别名, resource(4) of type (Person)

    第一个回调函数会在脚本中的相应类型的资源变量被释放掉的时候触发,比如作用域结束了,或者被unset()掉了
    第二个回调函数则是用在一个类似于长链接类型的资源上的,也就是这个资源创建后会一直存在于内存中,而不会在request结束后被释放掉。它将会在Web服务器进程终止时调用,相当于在MSHUTDOWN阶段被内核调用
*/
ZEND_API int zend_register_list_destructors(void (*ld)(void *), void (*pld)(void *), int module_number);
ZEND_API int zend_register_list_destructors_ex(rsrc_dtor_func_t ld, rsrc_dtor_func_t pld, const char *type_name, int module_number);

/*注册resource
 resource最终是保存在&EG(regular_list)这个系统HashTable中
*/
#define ZEND_REGISTER_RESOURCE(rsrc_result, rsrc_pointer, rsrc_type) zend_register_resource(rsrc_result, rsrc_pointer, rsrc_type TSRMLS_CC);

ZEND_API int zend_register_resource(zval *rsrc_result, void *rsrc_pointer, int rsrc_type TSRMLS_DC)
{
    int rsrc_id;
    rsrc_id = zend_list_insert(rsrc_pointer, rsrc_type TSRMLS_CC);
    if (rsrc_result) {
        rsrc_result->value.lval = rsrc_id;
        rsrc_result->type = IS_RESOURCE;
    }
    return rsrc_id;
}

ZEND_API int zend_list_insert(void *ptr, int type TSRMLS_DC)
{
    int index;
    zend_rsrc_list_entry le;

    le.ptr=ptr;
    le.type=type;
    le.refcount=1;
    index = zend_hash_next_free_element(&EG(regular_list));
    zend_hash_index_update(&EG(regular_list), index, (void *) &le, sizeof(zend_rsrc_list_entry), NULL);
    return index;
}

/*获取resource*/
#define ZEND_FETCH_RESOURCE(rsrc, rsrc_type, passed_id, default_id, resource_type_name, resource_type)
    rsrc = (rsrc_type) zend_fetch_resource(passed_id TSRMLS_CC, default_id, resource_type_name, NULL, 1, resource_type);
    ZEND_VERIFY_RESOURCE(rsrc);

/*校验resource*/      
#define ZEND_VERIFY_RESOURCE(rsrc)      \
if (!rsrc) {                        \
    RETURN_FALSE;                   \
}

3,代码说明

#define PERSON_RESOURCE_TYPE "Person"  //resource类型名称
static int person_len;                 //resource id
typedef struct _person {                //resource 结构
    char *name;
    int name_len;
    int age;
}person;

/*添加resource分类*/
PHP_MINIT_FUNCTION(resource){   
    person_len = zend_register_list_destructors_ex(person_dtor, NULL, PERSON_RESOURCE_TYPE, module_number);
    //person_len = zend_register_list_destructors(person_dtor, NULL, module_number);
    return SUCCESS;
}

/*释放resource资源,在脚本结束后执行*/
static void person_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC) {
    person *p = (person *)rsrc->ptr;
    php_printf("person refcount %d\n", rsrc->refcount);
    if (p->name) {
    efree(p->name);
    }
    efree(p);
}

/*实例化并注册resource*/
ZEND_BEGIN_ARG_INFO(person_create_arginfo, 0)
    ZEND_ARG_INFO(0, name)
    ZEND_ARG_INFO(0, age)
ZEND_END_ARG_INFO()
static PHP_FUNCTION(person_create) {
    char *name;
    int name_len;
    long age;
    person *new_person;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &name, &name_len, &age) == FAILURE) {
        return;
    }

    new_person = emalloc(sizeof(person));
    new_person->name = estrndup(name, name_len);
    new_person->name_len = name_len;
    new_person->age = age;

    ZEND_REGISTER_RESOURCE(return_value, new_person, person_len);
}

/*获取resource*/
ZEND_BEGIN_ARG_INFO(person_get_name_arginfo, 0)
    ZEND_ARG_INFO(0, person)
ZEND_END_ARG_INFO()
static PHP_FUNCTION(person_get_name) {
    zval *zperson;
    person *p;
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zperson) == FAILURE) {
        return;
    }
    ZEND_FETCH_RESOURCE(p, person*, &zperson, -1, PERSON_RESOURCE_TYPE, person_len);
    RETURN_STRING(p->name, 1);
}