High Performance OPC UA Server SDK
1.4.2.279
|
The High Performance SDK provides its own IPC (Inter Process Communication) framework.
This IPC framework is based on SHM (shared memory), which allows efficient interprocess communication without copying data across process boundaries.
The IPC components can describe their interface using an IDL (interface definition language). The ICC (interface C compiler) creates proxy and stub C code for the caller and callee side, based on the given IDL. This allows creating IPC components very easily.
The whole design of the High Performance SDK is based on a single threaded design using asynchronous functions and callbacks. The main application loop is never allowed to call any blocking function except uaapplication_timed_docom(). This function drives the timers, network communication, and the IPC framework. For this reason, our IPC framework generates asynchronous method functions with a corresponding callback based on synchronous function definitions in the IDL.
Example IDL:
The generate proxy function looks likes this on the caller side:
prio
parameters is used in the IPC framework to process queued operations according to their priority. Higher priorities will be processed first. Operations of same priority will be processed in FIFO order.This way the caller can start the operation asynchronously and gets a callback when the operation has finished.
On the callee side, the stub function is synchronous by default which makes the implementation easy:
The IPC functions are always called from the process main loop. There is no multithreading involved so you don’t need to care about race conditions.
Note that you should neither call any blocking functions in such IPC functions, nor do other long running operations which could block the main loop.
In case that the function is more complex than the multiply example above, e.g. if you want to delegate the operation to another asynchronous API, you might prefer asynchronous IPC stubs. Keep in mind that you are not allowed to call blocking functions like file I/O. In this example we’re using fictional asynchronous function for a firmware update.
The fictional API we want to use in this example looks like this:
To be able to call this via IPC we create the following IDL:
The keyword async
tells the ICC to generate an asynchronous function stub. The include
statement specifies a header file which should be included in the generated stub code as well.
The generated proxy code is asynchronous like in the previous example:
The generated stub code (begin_burn_impl
) is now also asynchronous:
This example assumes that you have an asynchronous API for implementing the asynchronous IPC call. Note that using a synchronous blocking implementation and calling stub_burn_complete
(via cb
) at the end of begin_burn_impl
would be wrong, because this would block processing the main loop. If you don’t have an asynchronous API, you need to create one by spawning a thread. So the above fictional API could be implemented like this:
It is easily possible to integrate the proxy/stub code generation into CMake. You only need to include the ICC CMake module and add the command ua_wrap_idl
. This will generate the Makefile commands to generate the code. The first two specified CMake variables receive the filenames for proxy and stub code. Either one of these or both need to be referenced by your build target, depending if this executable should contain proxy and stub code (single process configuration), or just one side (multi process configuration).
Example CMakeLists.txt: