CommonAPI C++ and bindings have been moved to github, see overview at https://github.com/orgs/GENIVI/teams/someip/repositories and see also the CommonAPI C++ homepage at http://genivi.github.io/capicxx-core-tools/. Please make sure that you use code generators and runtime libraries with the same version by getting the code generator binaries from capicxx-core-tools/releases repository, capicxx-dbus-tools/releases repository and capicxx-someip-tools/releases repository. Otherwise you could get same strange compilation errors. Please note that a newer version of this wiki page can be accessed via capicxx-core-tools/wiki repository.
Valid for CommonAPI 3.1.3 and vsomeip 1.3.0
Step 1: Preparation / Prerequisites
The following description is based on CommonAPI 3.1.3 and assumes that you use a standard Linux distribution (I tested it with Xubuntu 14.04) and that you have installed git and (CMake >=2.8).
Step 2: Build the CommonAPI Runtime Library
Start with fetching the source code of CommonAPI, e.g. with:
The CommonAPI runtime library can now be built without any other dependencies:
The output in your console should be similar to the extract of my output that it is the window above. Do not doubt when you see in your results that Doxygen or asciidoc is not found; it is only needed for the generation of the documentation. The package 'automotive-dlt' is only needed in case you want to get DLT log messages (see http://projects.genivi.org/diagnostic-log-trace/home). As shown in the last two lines you should find
libCommonAPI.so in your build directory.
The CommonAPI runtime library can be installed to
/usr/local (or any other directory if you set the installation prefix) by calling
make install. But I assume that in most of the cases this is not wanted; therefore this description explains the procedure completely without any installations.
Step 3: Build the CommonAPI D-Bus Runtime Library
Start again with cloning the source code of CommonAPI-D-Bus:
The D-Bus runtime library cannot be built without further preparations. The reason is that CommonAPI-D-Bus doesn't use the standard
libdbus library and needs a patched version. That means that you must first download, patch and build
libdbus before the CommonAPI D-Bus runtime can be built. Let's start (3 of 10 minutes have already passed ). Get and unpack the actual libdbus library:
I discarded the output in the console. Now apply the patches in the CommonAPI D-Bus source directory:
At the moment there are three libdbus patches provided. Two of these patches provide additional functions which will be called from CommonAPI.
Please check if all these patches could be applied successfully. I tested it with D-Bus 1.6.x and 1.8.x. For other versions I cannot guarantee that the patches work. If necessary updated patch versions will be provided for D-Bus > 1.8.x.
libdbus with autotools and check if the
so library has been created in the
Build libdbus with autotools. Otherwise you will miss some necessary files when you try to buld CommonAPI D-Bus.
Now it is possible to build the CommonAPI runtime library. Please note that you only use the uninstalled versions of CommonAPI and
libdbus. First create the build directory and change to the build directory:
For the next step add the path to your D-Bus directory to the actual PKG_CONFIG_PATH environment variable, start CMake and call make as usual:
If everything was successful (it should be!) you should find
libCommonAPI-DBus.so in your build directory. Make sure that there are no empty spaces in the path of your working directory.
Step 4: Write the Franca file and generate code
After all these preparations we start seriously to write a true CommonAPI application (more precisely two applications). We want to write one service which offers the method
sayHello and one client which calls this method. For CommonAPI services the description of offered interfaces is done by means of Franca IDL. Don't worry if you don't know Franca IDL, you will learn it very fast.
First create some directories and open a new empty ASCII file with the name
Now create the following interface:
Ready! A service which instantiates the interface
HelloWorld provides the function
sayHello which can be called. The next step is to generate code. For that we need the code generators. We copy them into the new subdirectory
cgen of our project directory:
Now you find the executables of the code generators in
cgen/commonapi_dbus_generator, respectively. There are four versions (Linux, Windows and 64bit variants). Type
uname -m if you don't know if you have a 32bit or 64bit version of Linux (you get
x86_64). For the further description we assume that you have the 32bit version.
Do not complain about details, such as that you have to call
chmod or that the names contain sometimes underscores and sometimes hyphen. It will change in future versions.
Finally you can generate code (CommonAPI code with the
commonapi-generator and CommonAPI D-Bus code with the
If everything worked, the generated code will be in the new directory
src-gen. The option
-sk generates a default implementation of your interface instance in the service.
Step 5: Write the client and the service application
Now we can start to write the Hello World application. Create new subdirectories
build in the project directory and change to
Now we have to create 4 files: The client code (
HelloWorldClient.cpp), one file for the main-function of the service (
HelloWorldService.cpp) and 2 files (header and source) for the implementation of the generated skeleton for the stub (we call it
Let's begin with the client. Create a new file
HelloWorldClient.cpp with the editor of your choice and type:
At the beginning of each CommonAPI application it is necessary to get a pointer to the generic runtime object. The runtime is necessary to create proxies and stubs. A client application has to call functions of an instance of an interface in the service application. In order to be able to call these functions we must build a proxy for this interface in the client. The interface name is the template parameter of the
buildProxy method; furthermore we build the proxy for a certain instance; the instance name is the second parameter in the
buildProxy method. In principle there is the possibility to distinguish between instances in different so-call domains (first parameter), but we don't want to discuss this in depth at the moment and take always the domain "local".
The proxy provides the API function
isAvailable; if the we start the service first then
isAvailable returns always
true. It is also possible to register a callback which is called when the service becomes available; but we try to keep it here as simple as possible.
Now we call the function
sayHello which we have defined in our fidl-file. The function has one in-parameter (string) and one out-parameter (also string). Have a look into
HelloWorldPorxy.hpp to get the information how exactly the function
sayHello must be called. Here it is important to know that it is possible to call the synchronous variant of this function (what we do here) or to call the asynchronous variant (
sayHelloAsync) which is slightly more complicated. One return value is the so-called
CallStatus, which gives us the information if the call was successful or not. Again, to keep it simple we do not check the CallStatus and hope that everthing worked fine.
We continue now to write the service. Create a new file
The main function of the service is even simpler as the main function of the client because the implementation of the interface functions is in the stub implementation. Again we need the pointer to the runtime environment; then we instantiate our implementation of the stub and register this instance of the interface by calling
registerService with an instance name. The service shall run forever and answer to function calls until it becomes killed; therefore we need the while loop at the end of the main function.
At the end we need the stub implementation; we realize it by creating a stub-implementation class which is inherited from the stub-default implementation. The header file is:
The implementation is in the cpp-file:
If the function
sayHello is called it gets the name (which is supposed to be the name of the developer of this application) and returns it with an added "Hello" in front. The return parameter is not directly the string as it is defined in the fidl-file; it is a standard function object with the return parameters as in-parameters. The reason for this is to provide the possibility to answer not synchronously in the implementation of this function but to delegate the answer to a different thread.
Step 6: Build and run
Since you must have installed CMake in order to build the CommonAPI runtime libraries, the fastest way to compile and build our applications is to write a simple CMake file. Create a new file
CMakeLists.txt directly in the project directory:
As include paths we need the include directories of CommonAPI and bindings and D-Bus; the directory of the generated code must be also added. We link everything together and do not discuss here questions concerning the configuration with different bindings. Therefore we tell CMake where to find the CommonAPI libraries and libdbus (replace the absolute paths with the paths on your machine). At the end we build two executables, one for the service and one for the client.
Now call CMake (remember that we created the build directory before:
Your output should look similiar. In the build direcory there should be two executables now: HelloWorldClient and HelloWorldService.