|
Hello,
will all CopyTo functions not supported anymore?
Especially for the builtin types Variant, NodeId, LocalizedText, ExpandedNodeId?
Our current server implementation works continuously with the Variant and NodeId CopyTo functions (in many cases with LocalizedText and QulifiedName too).
If this API change comes true, is there any alternative planned? Or must each server or client vendor implement these functionality by there own?
Regards
Martin |
|
Apologies for the inconvenience!
Most servers that we usually test against convert the data to their internal
representation and have little use for that functionality.
Furthermore the CopyTo functions are not very efficient, because there has
never been any CopyTo-Support in opcua_types.c. All the stack can do is
use the built-in serializer support to emulate the CopyTo functions.
The following code could be used to emutate CopyTo for any Scalar type,
but note that it is not really very efficient, and the error handling has
been omitted for simplicity.
#define IMPLEMENT_SCALAR_COPY(Type) \
OpcUaStatusCode OpcUa##Type##CopyTo(OpcUa##Type in, OpcUa_##Type out) \
{ \
extern OpcUa_EncodeableTypeTable OpcUa_ProxyStub_g_EncodeableTypes; \
extern OpcUa_StringTable OpcUa_ProxyStub_g_NamespaceUris; \
OpcUa_StatusCode uStatus; \
OpcUa_MessageContext cContext; \
OpcUa_Encoder pEncoder; \
OpcUa_Decoder pDecoder; \
OpcUa_Handle hContext; \
OpcUa_OutputStream pOutputStream; \
OpcUa_InputStream pInputStream; \
OpcUa_Byte pBuffer; \
OpcUa_UInt32 uBufferSize; \
OpcUa_UInt32 uInputSize; \
OpcUa_MessageContext_Initialize(&cContext); \
cContext.KnownTypes = &OpcUa_ProxyStub_g_EncodeableTypes; \
cContext.NamespaceUris = &OpcUa_ProxyStub_g_NamespaceUris; \
cContext.AlwaysCheckLengths = OpcUa_False; \
uStatus = OpcUa_BinaryEncoder_Create(&pEncoder); \
uStatus = OpcUa_MemoryStream_CreateWriteable(0, 0, &pOutputStream); \
uStatus = pEncoder->Open(pEncoder, pOutputStream, &cContext, &hContext); \
uStatus = pEncoder->Write##Type((OpcUa_Encoder)hContext, OpcUa_Null, in, OpcUa_Null); \
OpcUa_Encoder_Close(pEncoder, &hContext); \
OpcUa_Encoder_Delete(&pEncoder); \
uStatus = pOutputStream->Close((OpcUa_Stream)pOutputStream); \
uStatus = pOutputStream->GetPosition((OpcUa_Stream)pOutputStream, &uInputSize); \
uStatus = OpcUa_MemoryStream_GetBuffer(pOutputStream, &pBuffer, &uBufferSize); \
uStatus = OpcUa_MemoryStream_CreateReadable(pBuffer, uInputSize, &pInputStream); \
uStatus = OpcUa_BinaryDecoder_Create(&pDecoder); \
uStatus = pDecoder->Open(pDecoder, pInputStream, &cContext, &hContext); \
pDecoder->Read##Type((OpcUa_Decoder)hContext, OpcUa_Null, out); \
uStatus = pInputStream->Close((OpcUa_Stream)pInputStream); \
pInputStream->Delete((OpcUa_Stream)&pInputStream); \
pOutputStream->Delete((OpcUa_Stream)&pOutputStream); \
OpcUa_Decoder_Close(pDecoder, &hContext); \
OpcUa_Decoder_Delete(&pDecoder); \
OpcUa_MessageContext_Clear(&cContext); \
return uStatus; \
}
IMPLEMENT_SCALAR_COPY(Variant);
IMPLEMENT_SCALAR_COPY(NodeId); |
|
All right. I may be mistaken, but please, note how new version has become uncomfortable to use!
Let's see my example. I was working on the realization of View Service Set, particularly, the RegisterNodes/UnregisterNodes functions.
I consult the document "OPC UA Part 4". Both functions use NodeIds.
I implement RegisterNodes.
Page 41 says: "In case no optimization is supported for a Node, the Server shall return the NodeId from the request".
Let's say that it is my case. And I use OpcUa_NodeId_CopyTo and just copy identifiers from input args to output args.
But now I cannot copy anything, because there is no function here any more. And I have to rewrite the code.
I am going to look through the whole code of our project. But I am sure, that it is not the only case. Of course my team will fix everything... Of course you know what you are doing, however I think that you should not remove the "CopyTo(...)" function subset.
P.S. Thank you for the macro. |
|
Note that you should design your name space in a way
that makes it easy to use for yourself in the first place.
But maybe in your case where RegisterNodes does really nothing,
you could avoid all the copying if you overload the function
OpcUa_Server_BeginRegisterNodes, because then you can simply
move the pointer pRequest->NodesToRegister to pResponse->RegisteredNodeIds |