我目前正在使用 gSoap 库开发应用程序,并且对正确的用法库有一些误解。我生成了代理对象(-j 标志),它包装了我自己的类,如下所示。应用程序必须 24/7 全天候工作并同时连接到许多摄像机(~50 个摄像机),因此在每次请求后,我都需要清除所有临时数据。在每次请求后调用 soap_destroy() 和 soap_end() 是正常用法吗?因为每次请求后这样做似乎有点过分了。可能存在另一种正确使用的选项?
DeviceBindingProxy::destroy()
{
soap_destroy(this->soap);
soap_end(this->soap);
}
class OnvifDeviceService : public Domain::IDeviceService
{
public:
OnvifDeviceService()
: m_deviceProxy(new DeviceBindingProxy)
{
soap_register_plugin(m_deviceProxy->soap, soap_wsse);
}
int OnvifDeviceService::getDeviceInformation(const Access::Domain::Endpoint &endpoint, Domain::DeviceInformation *information)
{
_tds__GetDeviceInformation tds__GetDeviceInformation;
_tds__GetDeviceInformationResponse tds__GetDeviceInformationResponse;
setupUserPasswordToProxy(endpoint);
m_deviceProxy->soap_endpoint = endpoint.endpoint().c_str();
int result = m_deviceProxy->GetDeviceInformation(&tds__GetDeviceInformation, tds__GetDeviceInformationResponse);
m_deviceProxy->soap_endpoint = NULL;
if (result != SOAP_OK) {
Common::Infrastructure::printSoapError("Fail to get device information.", m_deviceProxy->soap);
m_deviceProxy->destroy();
return -1;
}
*information = Domain::DeviceInformation(tds__GetDeviceInformationResponse.Manufacturer,
tds__GetDeviceInformationResponse.Model,
tds__GetDeviceInformationResponse.FirmwareVersion);
m_deviceProxy->destroy();
return 0;
}
}
要确保正确分配和取消分配托管数据,请执行以下操作:
soap_destroy(soap);
soap_end(soap);
您希望经常执行此操作,以避免内存被旧数据填满。这些调用将删除所有反序列化数据以及使用 soap_new_X() 和 soap_malloc() 函数分配的数据。
所有托管分配都将被删除,后跟soap_destroy()
后跟soap_end()
。之后,您可以再次开始分配并再次删除,依此类推。
分配托管数据:
SomeClass *obj = soap_new_SomeClass(soap);
可以使用soap_malloc
进行原始托管分配,或者分配指针数组或 C 字符串:
const char *s = soap_malloc(soap, 100);
请记住,malloc 在C++并不安全。更好的是分配 std::string:
std::string *s = soap_new_std__string(soap);
数组可以用第二个参数分配,例如一个包含 10 个字符串的数组:
std::string *s = soap_new_std__string(soap, 10);
如果要保留通过这些调用删除的数据,请使用:
soap_unlink(soap, obj);
现在obj
可以稍后使用delete obj
删除。但请注意,obj
中指向托管数据的所有指针成员在soap_destroy()
和soap_end()
之后都已失效。因此,您可能必须在这些成员上调用soap_unlink()
,否则可能会悬而未决。
gSOAP 的一个新酷功能是自动生成任何数据结构的深度复制和删除函数,从而节省了大量的编码时间:
SomeClass *otherobj = soap_dup_SomeClass(NULL, obj);
这会将obj
复制到非托管堆空间。这是一个深层副本,用于检查对象图中的周期并删除此类周期以避免删除问题。还可以通过将soap
而不是 NULL 作为soap_dup_SomeClass
的第一个参数,将整个(循环)托管对象复制到另一个上下文。
要深度删除:
soap_del_SomeClass(obj);
这将删除obj
,还会删除其成员指向的数据,依此类推。
要使用soap_dup_X
和soap_del_X
函数,请使用 soapcpp2 分别带有选项-Ec
和-Ed
。
原则上,静态和堆栈分配的数据也可以序列化。但请考虑改用托管堆。
有关更多详细信息和示例,请参阅 https://www.genivia.com/doc/databinding/html/index.html#memory2。
希望这有帮助。
GSoap 文档的第 9.3 节中描述了必须处理内存的方式。