UA Ansi C Server Professional
 All Data Structures Functions Variables Typedefs Enumerations Enumerator Groups Pages
Unified Automation OPC UA SDK API Reference for ANSI C.


This manual is an API reference and also contains some general information about how to use the SDK. Please read the Introduction first before you start implementing to understand the principles of this SDK.

This manual is divided into the following sections:


A typical OPC UA Application is composed of three software layers. The following figure shows the three layers that can be implemented in a C / C++, in a .NET or a JAVA environment.

The OPC UA Stack implements the serialization, security and transport of messages exchanged between different UA Applications. The stack does not contain any application layer functionality. The OPC Foundation is providing different implementations of the stack. The Ansi C version has a platform layer that contains the platform specific code separated from the platform independent functionality.

A SDK simplifies the UA stack APIs, implements common UA functionality needed in most or all UA applications, provides base functionality and helper functions, implements the security handling and provides samples for common use cases.

The Application provides or consumes information via OPC UA. This layer contains the application specific logic and a mapping to OPC UA using the OPC SDKs.

The ANSI C OPC UA Server SDK provides a ANSI C library used to develop OPC UA Servers providing a standard interface to vendor specific systems. The OPC UA Server is normally used to describe the available information from a vendor system and to provide access to the data for external systems in a standard way.

The ANSI C OPC UA SDK is a basic OPC UA SDK designed for embedded devices which provides the basic infrastructure to create an OPC UA Server.

It supports the following OPC UA services:

  • FindServer, GetEndpoints
  • CreateSession, ActivateSession, CloseSession
  • Browse, Translate, RegisterNodes, UnregisterNodes
  • Read, HistoryRead
  • Write, HistoryUpdate
  • Call
  • CreateSubscription, ModifySubscription, DeleteSusbcription, TransferSubscriptions
  • CreateMonitoredItems, ModifyMonitoredItems, DeleteMonitoredItems
  • Publish, Republish

Coding Conventions

The SDK follows an object oriented design even if it's developed in ANSI C. It uses a special coding convention to offer functionality like C++ classes.
The following samples explain the principle of this coding convention.

The C++ way:

// Definition
class Foo
void doSomething(int x, int y);
int m_data;
// Usage
Foo *pObject = new Foo();
pObject->doSomething(5, 3);
delete pObject;

The ANSI C equivalent:

// Definition
struct _Foo
int data;
typedef struct _Foo Foo;
Foo* Foo_Create();
void Foo_Initialize(Foo *pThis);
void Foo_DoSomething(Foo *pThis, int x, int y);
void Foo_Clear(Foo *pThis);
void Foo_Delete(Foo *pThis);
// Usage
Foo *pObject;
pObject = Foo_Create();
Foo_DoSomething(pObject, 5, 3);

ANSI C Class Comparison:

ANSI CC++ equivalentDescription
<ClassName>_Create();new <ClassName>;Allocates a new object on the heap and calls the constructor.
<ClassName>_Initialize();<ClassName>::<ClassName>;The constructor initializes the object.
<ClassName>_Clear();<ClassName>::~<ClassName>;The destructor cleans up the object.
<ClassName>_Delete();delete ...Calls the destructor and frees the memory for this object on the heap.

ANSI C Polymorphism

This coding convention is straight forward and very simple, because it doesn't use any advanced object oriented features like inheritance, polymorphism or access specifiers (private, protected, ...).
The only exception to this rule are the files uaserver_basenode.h and uaserver_basenode.c. These are generated files using a specially developed C++ precompiler that outputs ANSI C code. It generates ANSI C structures like described above, but additionally supports inheritance and polymorphism. This precompiler generates structures where inherited variables are copied from the base 'class' and adds VTables to support polymorphism. There is no magic in this code, but we are using a compiler to generate it, because manually writing this would be very error-prone. e.g. you can call OpcUa_BaseNode_GetType(pObject) which is a 'virtual' function and the right GetType implementation is called through the function pointer in the VTable.
Polymorph Sample:

typedef OpcUa_BaseNode* OpcUa_BaseNodePtr;
OpcUa_BaseNodePtr NodeArray[10];
int i;
NodeArray[0] = OpcUa_Folder_Create();
NodeArray[1] = OpcUa_DataVariable_Create();
for (int i=0; i<10; i++)
NodeTypes type = OpcUa_BaseNode_GetType(NodeArray[i]); // call polymorph GetType function
OpcUa_BaseNode_Delete(NodeArray[i]); // call polymorph Delete function

Provider Architecture

The SDK follows a modular design where the generic code is separated from the application specific code. The Server implements generic functionality like implementing the UA Stack service table, subscription handling, monitored item management and offers the base class framework for creating an address space. The Server also creates the main UA Nodes "Root", "Objects", "Types" and "Views" that we call the "root address space".

The so called Providers implement application specific nodes using the server infrastructure and connect the server to their underlying IO data. One important Provider that comes with the SDK is the Server Provider. It implements the Server object that is defined by the OPC Foundation and is available in every OPC UA Server.

Provider Interface

The Provider Interface is the interface used by the Server to call a Provider. This interface is defined in _UaServer_pProviderInterface and must be implemented by every provider. The interface _UaServer_pProviderCBInterface defines a set of callback functions that a Provider can use to call the Server. This interface also contains functions to create new nodes and references in the Server's address space.

Interface functions and Dll Boundaries

The modular concept of the UA Server SDK allows to link the Data Providers statically into a single executable or dynamically using a dynamic library (e.g. *.dll on Windows, or *.so on linux/unix like systems).

The interface methods that cross these boundaries are implemented using the macros IFMETHOD and IFMETHODIMP just to simplify coding and to hide OS specific differences. Interface methods always have the return type OpcUa_StatusCode which is also provided by this macros.

#define IFMETHOD(name) typedef OpcUa_StatusCode (OPCUA_DLLCALL *UaServer_pfProvider##name)
#define IFMETHODIMP(name) OpcUa_StatusCode OPCUA_DLLCALL name

For example, the method definition and implementation of

return OpcUa_Good;

will be expanded by the pre-processor for Windows Dlls to

typedef OpcUa_StatusCode (__stdcall *UaServer_pfProviderCleanup)();
OpcUa_StatusCode __stdcall Cleanup()
return OpcUa_Good;

and on Linux or for statically linking simply to

typedef OpcUa_StatusCode (*UaServer_pfProviderCleanup)();
OpcUa_StatusCode Cleanup()
return OpcUa_Good;

All dynamic memory gets allocated through OpcUa_Alloc and is freed using OpcUa_Free which are macros from the OPC UA Stack that call the memory allocation function of the Stack.
Attention: If you decide to link the providers dynamically you also have to link against the OPC UA Stack dynamically to guarantee that there is only one OPC UA Stack with one CRT loaded. This way allocating and freeing memory across dll boundaries works without any problems.
If you link the providers statically you also can link the OPC UA Stack statically.