C · recipe
Connect to an OPC UA server in C
Create a client, apply the default configuration, then connect. open62541 returns a UA_StatusCode from everything: check it every time, because there are no exceptions to fall back on. Always delete the client to free its memory.
| Stack | open62541 |
|---|---|
| Version | 1.5.8 |
The code
#include <open62541/client_config_default.h>
#include <open62541/client_highlevel.h>
#include <open62541/plugin/log_stdout.h>
#include <stdio.h>
int main(void) {
UA_Client *client = UA_Client_new();
UA_ClientConfig_setDefault(UA_Client_getConfig(client));
UA_StatusCode rc = UA_Client_connect(client, "opc.tcp://opcua.umati.app:4840");
if (rc != UA_STATUSCODE_GOOD) {
printf("connect failed: %s\n", UA_StatusCode_name(rc));
UA_Client_delete(client);
return 1;
}
printf("connected\n");
/* read the namespace array: tells you what the server implements */
UA_Variant nsArray;
UA_Variant_init(&nsArray);
rc = UA_Client_readValueAttribute(client,
UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_NAMESPACEARRAY), &nsArray);
if (rc == UA_STATUSCODE_GOOD && nsArray.type == &UA_TYPES[UA_TYPES_STRING]) {
UA_String *uris = (UA_String *)nsArray.data;
for (size_t i = 0; i < nsArray.arrayLength; i++)
printf(" ns=%zu %.*s\n", i, (int)uris[i].length, uris[i].data);
}
UA_Variant_clear(&nsArray);
UA_Client_disconnect(client);
UA_Client_delete(client);
return 0;
}
/* build:
gcc client.c -lopen62541 -o client
or with the amalgamation:
gcc client.c open62541.c -lmbedtls -lmbedx509 -lmbedcrypto -o client
*/
What it prints
connected
ns=0 http://opcfoundation.org/UA/
ns=1 urn:umati:sample-server
ns=2 http://opcfoundation.org/UA/DI/
ns=3 http://opcfoundation.org/UA/Machinery/
Notes
- Every call returns a UA_StatusCode. Check it. There is no exception mechanism, and ignoring a return value here produces the memory bugs that give C a bad name.
- Every UA_Variant you initialise must be cleared with UA_Variant_clear, or you leak on every read.
- The single-file amalgamation is the practical way to vendor this into an existing embedded build without adopting its build system.
- Without mbedTLS or OpenSSL compiled in you get security policy None only, and no amount of configuration will change that.
- The Query service set and HTTPS are not implemented. Design around that rather than discovering it late.
What breaks first
The connection fails immediately with no useful message
Check TCP reachability to port 4840 first, then that the endpoint path is right. UA_StatusCode_name turns the numeric code into something you can search for.
BadConnectionRejectedCheck TCP reachability to port 4840 first, then that the endpoint path is right. UA_StatusCode_name turns the numeric code into something you can search for.
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.