I wrote a C++ library that exposes a number of classes. I also wrote a php extension using zend, as a wrapper over the c++ library.
I have a problem properly serializing my objects, when, for example, I try to store them in $_SESSION.
Here is an example:
struct spider_object
{
zend_object m_std;
Spider::QGramTokenizer* m_pObject;
};
...
zend_class_entry *spider_QGramTokenizer_ce;
PHP_METHOD(spider_QGramTokenizer, __construct)
{
long lQGramSize;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &lQGramSize) == FAILURE)
{
WRONG_PARAM_COUNT;
}
Spider::QGramTokenizer* pQT = new Spider::QGramTokenizer(static_cast<uint16_t>(lQGramSize));
spider_object* pO = static_cast<spider_object*>(zend_object_store_get_object(getThis() TSRMLS_CC));
pO->m_pObject = pQT;
}
PHP_METHOD(spider_QGramTokenizer, getQGramSize)
{
spider_object *pO = static_cast<spider_object*>(zend_object_store_get_object(getThis() TSRMLS_CC));
Spider::QGramTokenizer* pQT = static_cast<Spider::QGramTokenizer*>(pO->m_pObject);
if (pQT != NULL)
{
RETURN_LONG(pQT->getQGramSize());
}
else
zend_error(E_ERROR, "Null QGramTokenizer instance.\n");
}
I create a spider_QGramTokenizer object in my script and it works great. Once I store it as a session variable and try to get it from a different script, I get the object back fine, but if I call getQGramSize for example then I get a "Null QGramTokenizer instance" error.
In other words, serialize() does not know how to __sleep or __wakeup the spider_object::m_pObject instance and it simply sets it to null. Or, in fact, the whole spider_object instance stored in zend_object_store does not get serialized at all.
I thought of overriding __sleep and __wakeup, but I have no clue what zend does under the hood and what the return array from __sleep needs to be, plus how do I piggyback my own m_pObject related data in there? Is that possible?开发者_运维技巧
When objects in PHP are unserialized, the constructor is not called (again) as the instance was already constructed (then serialized and then finally unserialzed). This should at least explain the behavior you see (compare: How does Doctrine 2 retrieve entities without calling the entity's constructor?).
I don't know which routines the PHP extension API offers for unserialization, however if you're able to store the instance of your C++ object in a PHP private member, it will be available after serialization.
I can't say if __sleep
and __wakeup
can be defined within the C code as well, probably this works. But I'm not a PHP extension developer so my expertise is none in this field.
精彩评论