Storing Structs in Global Hashes in PHP C extensions
After fighting for a few days, (And eventually failing), I thought I'd
try again to find an example of storing hashes in an extension.
Thankfully the SOAP extension has a good (well as far as I know it
works) example.
In the header file.. create your stuct, and the hash in your globals.
typedef struct _mystruct mystruct, *mystructPtr;
struct _mystruct {
int a;
char *b;
};
ZEND_BEGIN_MODULE_GLOBALS(myext)
HashTable myhash;
......
......
ZEND_END_MODULE_GLOBALS(myext)
Somewhere near the beginning of the C file declare you have globals.
This is included in the skeleton
ZEND_DECLARE_MODULE_GLOBALS(myext)
You need to provide a destructor for the struct (so it gets free'd)
static void mystruct_dtor(void **ptr)
{
mystruct *mystr = (mystr *)*ptr;
if (!mystr) return;
if (mystr->b) efree(mystr->b);
efree(mystr);
}
create a modules init globals method
This is where the hash can be initalized.
static void myext_globals_init(zend_myext_globals *myext_globals)
{
....
zend_hash_init_ex(&myext_globals->myhash, 0, NULL, (dtor_func_t) mystruct_dtor, 1, 0);
.....
}
Next in the MINIT - create the memory for the global.
PHP_MINIT_FUNCTION(myext)
{
ZEND_INIT_MODULE_GLOBALS(myext, myext_globals_init, NULL);
}
Adding / Upating entries
long enc;
mystruct *mystr;
mystr = emalloc(sizeof(myStruct));
mystr->a = 1;
mystr->b = estrdup("TEST");
enc = (long)mystr
zend_hash_add(&MYEXT_G(myhash), str, strlen(str) + 1, &enc, sizeof(mystructPtr), NULL);
or (testing existance/ updating. )
if ( zend_hash_exists(&MYEXT_G(myhash), str, strlen(str) + 1) ) {
zend_hash_add_or_update(&MYEXT_G(myhash), str, strlen(str) + 1, &enc, sizeof(mystructPtr), NULL);
}
Finding / fetchting entries
mystructPtr *mstPtr;
mystruct *mst
zend_hash_find(&MYEXT_G(myhash), str, strlen(str) + 1, (void)&mstPtr TSRMLS_CC);
/* get the struct to work with */
mst = *mstPtr;
print("mystruct b is %s\n", mst->b);
Shutdown destruction
PHP_MSHUTDOWN_FUNCTION(soap)
{
zend_hash_destroy(&MYEXT_G(myhash));
....
return SUCCESS;
}