gSoap

时间:2017-03-23 11:58:37

标签: c++ gsoap onvif

我目前正在使用gSoap库开发应用程序,并对正确的使用库有一些误解。我已经生成了包含我自己的类的代理对象(-j标志),如下所示。应用程序必须全天候工作并同时连接到许多摄像机(~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;
    }

}

2 个答案:

答案 0 :(得分:1)

确保妥善分配和取消分配托管数据:

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。但请注意,objsoap_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_Xsoap_del_X函数,请分别使用soapcpp2选项-Ec-Ed

原则上,静态和堆栈分配的数据也可以序列化。但请考虑使用托管堆。

有关详细信息和示例,请参阅https://www.genivia.com/doc/databinding/html/index.html#memory2

希望这有帮助。

答案 1 :(得分:0)

Section 9.3 of the GSoap documentation中描述了必须处理内存的方式。