Writeing OO exteions for PHP 4.3

php.internals

Jan Gerritsen

22 years ago
Hello, I want to write an OO extension in C++ for my PHP 4.3.8 under linux. I have already written some extensions in C for my own purposes, which introduce new functions to PHP. Studying the sources of ext/standard/dir.c, ext/ming/ming.c and the tutorial from J Smith (http://bugs.tutorbuddy.com/phpcpp/phpcpp/) I got already this far: I have managed to build and link the CPP sources as a shared object which can be loaded and called from PHP. I have introduced the new class to PHP using the following code in the PHP_MINIT_FUNCTION of my extension: static zend_class_entry *url_class_entry_ptr; static int le_url; function_entry url_class_functions[] = { PHP_FALIAS(url, url_init, NULL) PHP_FALIAS(set_string, url_set_string, NULL) {NULL, NULL, NULL} }; static ZEND_RSRC_DTOR_FUNC(destroy_url) { if (rsrc->ptr) { delete (Url_class*) rsrc->ptr; rsrc->ptr = NULL; } } PHP_MINIT_FUNCTION(url) { zend_class_entry url_class_entry; INIT_CLASS_ENTRY(url_class_entry, "url", url_class_functions); url_class_entry_ptr = zend_register_internal_class(&url_class_entry TSRMLS_CC); le_url = zend_register_list_destructors_ex(destroy_url, NULL, "url", module_number); return SUCCESS; } This class can be created, and the functions (methods) can be called from PHP. Example: $url = new URL(); $url->set_string("12345"); Now my problem is, how can I save the pointer of my C++ class, created in the url_init function, and restore it in the other functions/methods: PHP_FUNCTION(url_init) { Url_class * url = new Url_class; / * code to save the address of url */ } PHP_FUNCTION(url_set_string) { Url_class *url = NULL; /* code to fetch url */ if( url != NULL ) { url->set_string(“test”); RETURN_TRUE; } RETURN_FALSE; } I could not work out how to do this, by studying the code of the OO extensions I mentioned. Can someone give me a hint, ore some example code, how to do such things? thanks Jan Gerritsen

John Coggeshall

21 years ago
If I understand you correctly you can put this pointer inside of a resource container and return the resource container to user space as the return value from url_init(). Then, from url_set_string() you accept the resource as a parameter and extract the pointer to your CPP instance of whatever class. John On Fri, 2004-09-03 at 10:54, Jan Gerritsen wrote:

Jan Gerritsen

21 years ago
Hi,
> If I understand you correctly you can put this pointer inside of a > resource container and return the resource container to user space as > the return value from url_init(). Then, from url_set_string() you accept > the resource as a parameter and extract the pointer to your CPP instance > of whatever class.
Tanks for your response, but your solution do not work for me, because I don’t get the resource_id as parameter for calls to the object. ($php_url_object->set_string(“asdf”); ) I now save the C++ Object pointer in a resource and save this resource as an attribute of the PHP object. PHP_FUNCTION(url_init) { Url_class * url = new Url_class; zval * this_p = getThis(); MAKE_STD_ZVAL(return_value); int res_id = ZEND_REGISTER_RESOURCE(NULL, url, le_url); add_property_resource(getThis(), "url_class_ressource", res_id); } It’s a little bit tricky to extract this resource and the inherit pointer again, like I do in my set_string function: PHP_FUNCTION(url_set_string) { zval ** ressource; if( zend_hash_find(getThis()->value.obj.properties, "url_class_ressource", sizeof("url_class_ressource"), (void**) &ressource) == FAILURE ) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not find url_class_ressource"); RETURN_FALSE; } if( ressource == NULL || (*ressource) == NULL ||(*ressource)->type != IS_RESOURCE ) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Ressource not found"); RETURN_FALSE; } Url_class * url; url = (Url_class *) zend_fetch_resource(ressource TSRMLS_CC, -1, "url", NULL, 1, le_url); ZEND_VERIFY_RESOURCE(url); if( url == NULL ) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Ressource is invalid???"); RETURN_FALSE; } if(url->setString("test")) { RETURN_TRUE; } RETURN_FALSE; } But I don’t get memory leeks, because php makes sure my resource is destructed if it is not referenced anymore: static ZEND_RSRC_DTOR_FUNC(destroy_url) { Url_class * url = (Url_class *) rsrc->ptr;; delete url; } I am not to happy with this solution, because the user can access the "url_class_ressource" attribute of the PHP url Object, but this will work for now. Or can someone give me better solution? I am happy for everything which may help me,… Greets Jan

George Schlossnagle

21 years ago
On Sep 3, 2004, at 2:33 PM, Jan Gerritsen wrote:
> Hi, > >> If I understand you correctly you can put this pointer inside of a >> resource container and return the resource container to user space as >> the return value from url_init(). Then, from url_set_string() you >> accept >> the resource as a parameter and extract the pointer to your CPP >> instance >> of whatever class. > > Tanks for your response, but your solution do not work for me, because > I don’t get the resource_id as parameter for calls to the object. > ($php_url_object->set_string(“asdf”); ) > I now save the C++ Object pointer in a resource and save this resource > as an attribute of the PHP object.
This is a typical strategy for php4 oo stuff. George