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
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
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
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
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