Jump to content


New Members
  • Posts

  • Joined

  • Last visited


About micha

  • Birthday 10/24/1976

Contact Methods

  • Website URL
  • ICQ

Profile Information

  • Gender
    Not Telling
  • Location

micha's Achievements


Newbie (1/5)



  1. Hi daeken, wow, thanks for your fast response. Yeah, this is ok since all vars are private (php4) and have appropriate get and set methods. However, theoretically it should be possible to have both by storing the same pointer into the objects property hashtable and into the resources structure, shouldn't it ? Ok, great. They are all used internally and as a nice side effect I get *real* private vars and can be sure that the user doesn't change them. Btw, do you know if fetching a resource is as fast as finding a hash entry...or even faster ? Thx, micha
  2. Hi, I wonder if a resource could be an option for storing object properties due to performance issues ? In most of the class methods I have to access more than on member variable, so if I need access to e.g. 4 vars, zend_hash_find has to be called 4 times. For a resource which holds a structure with all member vars one call to ZEND_FETCH_RESOURCE would do it. Well, does this make sense ? micha
  3. Well, it's not. I compiled the code with a debug enabled php version today and got dozens of memory leaks... Therefore I took the call_user_function_ex function and removed all not needed for calling an internal function. int call_internal_function(zend_function *function, zval **retval_ptr_ptr, int param_count, zval **params[] TSRMLS_DC) { zval **original_return_value; zend_function_state *original_function_state_ptr; zend_execute_data execute_data; zend_op temp_op; int i; if (! function || function->type != ZEND_INTERNAL_FUNCTION) { return FAILURE; } /* Initialize execute_data */ EX(fbc) = NULL; EX(object).ptr = NULL; EX(ce) = NULL; EX(Ts) = NULL; EX(op_array) = NULL; EX(opline) = NULL; EX(function_state).function = function; *retval_ptr_ptr = NULL; original_function_state_ptr = EG(function_state_ptr); for (i=0; i < param_count; i++) { zval *param; if (EX(function_state).function->internal_function.arg_types && i < EX(function_state).function->internal_function.arg_types[0] && EX(function_state).function->internal_function.arg_types[i+1]==BYREF_FORCE && !PZVAL_IS_REF(*params[i])) { if ((*params[i])->refcount>1) { zval *new_zval; ALLOC_ZVAL(new_zval); *new_zval = **params[i]; zval_copy_ctor(new_zval); new_zval->refcount = 1; (*params[i])->refcount--; *params[i] = new_zval; } (*params[i])->refcount++; (*params[i])->is_ref = 1; param = *params[i]; } else if (*params[i] != &EG(uninitialized_zval)) { (*params[i])->refcount++; param = *params[i]; } else { ALLOC_ZVAL(param); *param = **(params[i]); INIT_PZVAL(param); } zend_ptr_stack_push(&EG(argument_stack), param); } zend_ptr_stack_n_push(&EG(argument_stack), 2, (void *) (long) param_count, NULL); EG(function_state_ptr) = &EX(function_state); EX(prev_execute_data) = EG(current_execute_data); EG(current_execute_data) = &execute_data; ALLOC_INIT_ZVAL(*retval_ptr_ptr); temp_op.extended_value = param_count; temp_op.result.u.var = 0; temp_op.lineno = 0; EX(opline) = &temp_op; EX(Ts) = (temp_variable *) do_alloca(sizeof(temp_variable)*1); EX(Ts)[EX(opline)->result.u.var].var.ptr = *retval_ptr_ptr; if (!zend_execute_internal) { ((zend_internal_function *) EX(function_state).function)->handler(EX(opline)->extended_value, EX(Ts)[EX(opline)->result.u.var].var.ptr, EX(object).ptr, 1 TSRMLS_CC); } else { zend_execute_internal(&execute_data, 1 TSRMLS_CC); } INIT_PZVAL(*retval_ptr_ptr); free_alloca(EX(Ts)); zend_ptr_stack_clear_multiple(TSRMLS_C); EG(function_state_ptr) = original_function_state_ptr; EG(current_execute_data) = EX(prev_execute_data); return SUCCESS; } The example with mysql_escape_string now looks as follows: ZEND_API zval *ext_mysql_escape_string(zval *str TSRMLS_DC) { zval *retval, **args[1]; zend_function function; /* initialize internal function */ function.internal_function.type = ZEND_INTERNAL_FUNCTION; function.internal_function.arg_types = NULL; function.internal_function.function_name = "mysql_escape_string"; function.internal_function.handler = zif_mysql_escape_string; args[0] =& str; call_internal_function(&function, &retval, 1, args TSRMLS_CC); return retval; } No memory leaks are reported this way, so I hope it's ok now. Btw, take into account that if the internal function requires a parameter passed by reference, you need to adapt function.internal_function.arg_types so that call_internal_function is able to separate the zval. Example with a function that takes one argument : unsigned char args[] = {1, BYREF_FORCE}; /* initialize internal function */ function.internal_function.type = ZEND_INTERNAL_FUNCTION; function.internal_function.arg_types = args; function.internal_function.function_name = "some_function_name"; function.internal_function.handler = zif_some_function; Please correct me if I'm wrong ! micha
  4. Hi ede, I have nearly the same problem for a while now, in fact not calling own class functions but functions from extensions, e.g. mysql_connect(). There's little to nothing on documentation and the source does have all but comments I'm porting an object orientated database abstraction layer written in php to a C extension. I was searching for the best way to call functions from already existing database extensions like mysql, etc. As I got nothing else to work than call_user_function_ex I used this until I was able to do basic benchmarks. Well, calling internal functions with call_user_function_ex is nearly as slow as executing the php version itself... So I was searching for a better way again and came across your post and zend_ptr_stack_push. I tried this before, but missed the call to zend_ptr_stack_n_push. With this call it seems to work now, here's an example for mysql_escape_string(): ZEND_API zval *ext_mysql_escape_string(zval *str TSRMLS_DC) { zval *retval; long param_count=1; MAKE_STD_ZVAL(retval); zend_ptr_stack_push(&EG(argument_stack), str); zend_ptr_stack_n_push(&EG(argument_stack),2,(void*)(long)param_count,NULL); zif_mysql_escape_string(param_count, retval, NULL, 1 TSRMLS_CC); if (Z_TYPE_P(retval) != IS_STRING) { zval_ptr_dtor(&retval); return NULL; } return retval; } Anyway, I do not know if this is the right way... Your problem with calling the parent constructor I solved as follows: [i]Parent class:[/i] ZEND_FUNCTION(Item) { php_Item(getThis() TSRMLS_CC); } ZEND_API void php_Item(zval *this_ptr TSRMLS_DC) { if (Z_TYPE_P(this_ptr) != IS_OBJECT) { object_init_ex(this_ptr, Item_ce_ptr); } add_property_string(...) ... } [i]Child class:[/i] ZEND_FUNCTION(StringItem) { //... php_StringItem(getThis() TSRMLS_CC); } ZEND_API void php_StringItem(zval *this_ptr TSRMLS_DC) { object_init_ex(this_ptr, StringItem_ce_ptr); php_Item(this_ptr TSRMLS_CC); add_property_string(...) } Hope this helps. micha
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.