序列化 c++ 时出现问题通过 php 扩展访问的类
我编写了一个公开许多类的 C++ 库。我还使用 zend 编写了一个 php 扩展,作为 C++ 库的包装器。
我在正确序列化我的对象时遇到问题,例如,当我尝试将它们存储在 $_SESSION 中时。
这是一个示例:
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");
}
我在脚本中创建了一个 Spider_QGramTokenizer 对象,并且效果很好。一旦我将它存储为会话变量并尝试从不同的脚本获取它,我就可以很好地返回对象,但是如果我调用 getQGramSize 例如,我会收到“Null QGramTokenizer 实例”错误。
换句话说,serialize() 不知道如何 __sleep 或 __wakeup Spider_object::m_pObject 实例,它只是将其设置为 null。或者,事实上,整个spider_object实例存储在zend_object_store中 根本没有被序列化。
我想过重写 __sleep 和 __wakeup,但我不知道 zend 在下面做什么 引擎盖以及 __sleep 的返回数组需要是什么,以及我如何搭载我自己的数组 m_pObject相关数据在那里?这可能吗?
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
当 PHP 中的对象被反序列化时,不会(再次)调用构造函数,因为实例已经被构造(然后序列化,最后被反序列化)。这至少应该解释您看到的行为(比较:Doctrine 2 如何在不调用实体构造函数的情况下检索实体?)。
我不知道 PHP 扩展 API 提供哪些例程用于反序列化,但是如果您能够将 C++ 对象的实例存储在 PHP 私有成员中,那么它将在序列化后可用。
我不能说
__sleep
和__wakeup
是否也可以在 C 代码中定义,也许这有效。但我不是 PHP 扩展开发人员,所以我在这个领域没有专业知识。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.