C · recipe
Decode custom structures in C
open62541 can read a server's DataTypeDefinitions at runtime, but in C the pragmatic path for a known model is to generate types at build time from a NodeSet2 file. Runtime decoding of an unknown structure means walking the ExtensionObject yourself.
| Stack | open62541 |
|---|---|
| Version | 1.5.8 |
The code
#include <open62541/client_config_default.h>
#include <open62541/client_highlevel.h>
#include <stdio.h>
int main(void) {
UA_Client *client = UA_Client_new();
UA_ClientConfig_setDefault(UA_Client_getConfig(client));
if (UA_Client_connect(client, "opc.tcp://opcua.umati.app:4840") != UA_STATUSCODE_GOOD) {
UA_Client_delete(client); return 1;
}
UA_Variant v;
UA_Variant_init(&v);
UA_StatusCode rc = UA_Client_readValueAttribute(
client, UA_NODEID_NUMERIC(4, 7001), &v);
if (rc == UA_STATUSCODE_GOOD &&
v.type == &UA_TYPES[UA_TYPES_EXTENSIONOBJECT]) {
UA_ExtensionObject *eo = (UA_ExtensionObject *)v.data;
if (eo->encoding == UA_EXTENSIONOBJECT_DECODED) {
printf("decoded, type: %s\n", eo->content.decoded.type->typeName);
/* cast eo->content.decoded.data to the generated struct */
} else {
printf("still encoded: %zu bytes of body\n",
eo->content.encoded.body.length);
printf("-> the type is not known to this client\n");
}
}
UA_Variant_clear(&v);
UA_Client_disconnect(client);
UA_Client_delete(client);
return 0;
}
/* Preferred for a known model: generate types at build time.
open62541 ships generators that turn a NodeSet2 XML file into C structs
and the matching data type array, which you then register on the client. */
What it prints
still encoded: 48 bytes of body
-> the type is not known to this client
# after registering generated types for the model:
# decoded, type: ProductionJobType
Notes
- In C, prefer build-time generation from the NodeSet2 file when the model is known and stable. It gives you real structs and no runtime type machinery.
- An ExtensionObject with encoding UA_EXTENSIONOBJECT_ENCODED_BYTESTRING means the client does not know the type. That is information, not a failure.
- Runtime decoding of arbitrary structures in C is possible but rarely worth it on an embedded target. If you need it, consider whether that component belongs in C at all.
- Unions and optional fields are where generated decoders break. Test them against real server data.
What breaks first
The structure never decodes and you only ever see bytes
Register the type with the client, either from generated build-time types or by loading the server's DataTypeDefinitions.
BadDataEncodingUnsupportedRegister the type with the client, either from generated build-time types or by loading the server's DataTypeDefinitions.
Other recipes in this stack
Concepts on this page
Last verified 7 September 2026 against OPC UA 1.05.07. OPC UA Connect is an educational resource and is not affiliated with the OPC Foundation.