質問

I write a php extension which contains a simple method, and it works well. I want to call "mysql_connect" method in this method. I have tried to find some documents or some guides ,but failed.

My extension method code is here:

PHP_FUNCTION(wdd_mysql_connect)
{
char *name;
int name_len;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE)
{
    return;
}
php_printf("Hello %s!", name);
// how to call mysql_connect????????
RETURN_TRUE;
}
役に立ちましたか?

解決

Basically, you call zend_call_function(). Example of two helper functions to do that:

/* {{{ zval*** get_params_ex(const char *fmt,size_t len, va_list argp) */
static zval*** get_params_ex(const char *fmt, size_t len TSRMLS_DC, va_list argp) {
    zval*** params;
    size_t i, j;

    char *s=NULL;
    long l=-1,r=-1;
    double d=-1;
    zval *z=NULL;
    zend_bool b=0;


    params = safe_emalloc(len, sizeof(zval**), 0);
    if(NULL == params) {
        return NULL;
    }
    for(i=0; i < len; i++) {
        params[i] = emalloc(sizeof(zval*));
    }

    for(i=0; i < len; i++) {
        switch(fmt[i]) {
        case 's':
            s = va_arg(argp, char*);
            MAKE_STD_ZVAL(*params[i]);
            ZVAL_STRING(*params[i], s, 1);
            break;
        case 'l':
            l = va_arg(argp, long);
            MAKE_STD_ZVAL(*params[i]);
            ZVAL_LONG(*params[i], l);
            break;
        case 'd':
            d = va_arg(argp, double);
            MAKE_STD_ZVAL(*params[i]);
            ZVAL_DOUBLE(*params[i], d);
            break;
        case 'b':
            b = va_arg(argp, int);
            MAKE_STD_ZVAL(*params[i]);
            ZVAL_BOOL(*params[i], b);
            break;
        case 'r':
            r = va_arg(argp, long);
            MAKE_STD_ZVAL(*params[i]);
            ZVAL_RESOURCE(*params[i], r);
            break;
        case 'z':
            z = va_arg(argp, zval*);
            if(NULL != z) {
                *params[i] = z;
            }
            else {
                ALLOC_INIT_ZVAL(*params[i]);
            }
            break;
        default:
            php_error_docref(NULL TSRMLS_CC, E_CORE_ERROR, "Unexpected character '%c' in format specifier \"%s\"", fmt[i], fmt);
            for(j = 0; j < i; j++) {
                zval_ptr_dtor(params[j]);
            }
            efree(params);
            return NULL;
        }
    }
    return params;

}
/* }}} */
/* {{{ META_API zval* obj_call_method_internal_ex(zval *obj, zend_class_entry *ce, zend_function *func, zend_class_entry* calling_scope, zend_bool native_null TSRMLS_DC, char* fmt, ...)
 * call method func of the object obj of type ce from the specified scope and return the value returned by the calee.
 * if native_null is true, and the method returns a IS_NULL zval, then free that zval and return a NULL pointer
 * valid format specifiers are [sldbrz] for string, long, double, boolean, resource, zval */
META_API zval* obj_call_method_internal_ex(zval *obj, zend_class_entry *ce, zend_function *func, zend_class_entry* calling_scope,
        zend_bool native_null TSRMLS_DC, char* fmt, ...) {
    zval ***params;
    int argc;
    zval *retval_ptr;
    zend_fcall_info fci;
    zend_fcall_info_cache fcc;

    if(NULL != fmt) {
        va_list argv;

        argc = strlen(fmt);
        va_start(argv, fmt);
        params = get_params_ex(fmt, argc TSRMLS_CC, argv);
        va_end(argv);
    }
    else {
        argc = 0;
        params = NULL;
    }

    retval_ptr = NULL;

    fci.size = sizeof(fci);
    fci.function_table = EG(function_table);
    fci.function_name = NULL;
    fci.symbol_table = NULL;
    fci.object_ptr = obj;
    fci.retval_ptr_ptr = &retval_ptr;
    fci.param_count = argc;
    fci.params = params;
    fci.no_separation = 1;

    fcc.initialized = 1;
    fcc.function_handler = func;
    fcc.object_ptr = obj;
    fcc.calling_scope = calling_scope;
    fcc.called_scope = ce;

    /*if we want the object, and the object is not an object yet, we init it*/
    if(func == ce->constructor) {
        if(IS_NULL == Z_TYPE_P(obj)) {
            object_init_ex(obj, ce);
        }
        else {
            php_error_docref(NULL TSRMLS_CC, E_CORE_ERROR, "Cannot create an object");
            native_null = 1;
            goto clean_params;
        }
    }

    if(FAILURE == zend_call_function(&fci, &fcc TSRMLS_CC)) {
        php_error_docref(NULL TSRMLS_CC, E_CORE_ERROR, "Cannot call %s::%s", ce->name, func->common.function_name);
        if(NULL != retval_ptr) {
            zval_ptr_dtor(&retval_ptr);
        }
    }
clean_params:
    if(NULL != params) {
        int i;
        for(i=0; i < argc; i++) {
            zval_ptr_dtor(params[i]);
            efree(params[i]);
        }
        efree(params);
    }
    if(func == ce->constructor) {
        zval_ptr_dtor(&retval_ptr);
        retval_ptr = fci.object_ptr;
    }
    else {
        if(native_null) {
            if(NULL != retval_ptr && IS_NULL == Z_TYPE_P(retval_ptr)) {
                zval_ptr_dtor(&retval_ptr);
                retval_ptr = NULL;
            }
            else {
                php_error_docref(NULL TSRMLS_CC, E_CORE_ERROR, "The call %s::%s() does not return NULL as expected", ce->name, func->common.function_name);
            }
        }
    }
    return retval_ptr;
}
/* }}} */
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top