2

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;
}
0

1 Answer 1

1

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;
}
/* }}} */
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.