Including C++ code

  1. Building a Cplusplus Library for the XDK
  2. Binding a Cplusplus Library in the SDK

Coding for the XDK is mainly based on the programming language C, but sometimes it could be useful to include C++ code. Especially if certain libraries are not available in plain C, a C++ implementation comes into play. This section guides step by step how to wrap the C++ functionality and how to modify the makefiles of the SDK. This will allow you to compile and link C++ code into an XDK application.

Building a Cplusplus Library for the XDK

To be able to implement C++ libraries for the XDK, these libraries need to be present with their implementation and header files. This is necessary, because the compiling process of the XDK-Workbench will be used in the later chapter to build these files into object files, containing the correct flags for the XDK target platform.

Additionally, it is important to wrap the C++ functionality into C wrapper functions and then to implement the functionality in the XDK application over the wrapper functions.

First, you need to create a new header file for your C++ library (e.g. CppWrapper.h) and a new source file (e.g. CppWrapper.c). These two new files will suit as wrapper interface for the C++ functionality. The code snippets below will give an indication, about how the wrapper functions should be build.

Please note, the header and source file for the wrapper interface do not need to be built in the XDK-Workbench. A text editor for example should be sufficient too.

The prototype and variable declarations should look in the wrapper header file as follows:

#ifdef __cplusplus
extern "C" {
#endif

// Place your prototype and variable declarations here

#ifdef __cplusplus
}
#endif

The extern "C" keyword will tell the C++ compilation process to interpret the declared functions within the body of the extern "C" keyword as C functions. Only their names, not their input parameters will be used for the respective functions.

In case of classes, these should be given a struct alias over the following implementation, to work in the wrapper function.

typedef struct testClass testClass;

The wrapper source file needs an included extern "C" call to cover all implementations of the wrapper functions in its body:

extern "C" {

// Place all your implementations of the wrapper functions here

}

To use your implemented C++ library later on, the library header file needs to get included into the wrapper source file like e.g.:

#include "NameOfTheCppLibrary.h"

To ensure your libraries will work properly when flashed on the XDK, the armGCC compiler, which is provided with your XDK-Workbench installation should be used. To do so, please browse to the armGCC compiler binary folder by using your Windows/Linux/Mac command line. The default path for the armGCC compiler binary folder is, for example for Windows, C:\XDK-Workbench\armGCC\bin.

Create object files (e.g. CppWrapper.o) from the previously implemented wrapper source file and also from all implementation files your C++ library uses, by executing the command below.

arm-none-eabi-g++ $PATH\CppWrapper.c -c -Wall -pedantic -mcpu=cortex-m3 -mthumb -o $PATH\CppWrapper.o

This command will build an object file including all necessary flags for the cortex-m3 micro-controller on the XDK. Make sure to replace $PATH with the actual path of your wrapper source file and your C++ library source files.

Once all library object files are successfully created, these need to be packed into an archive file (e.g. CppWrapper.a).

For building an archive file with different object files, the command below should be used.

arm-none-eabi-ar -r $PATH\CppWrapper.a $PATH\CppWrapper.o $PATH\CppLibrary.o

Make sure to replace $PATH with the previous used path, which contains all the project’s own source, header and now object files. Please note that an archive file can contain multiple object files and therefore all need to be placed after the command arm-none-eabi-ar -r, behind the archive file’s name with their corresponding paths.

Furthermore, the archive file will work without any issues on the XDK.

To make these steps easily repeatable, you might want to consider creating a batch file (.bat) or script file, with these two command lines. Batch and script files can be executed from the operating system’s terminal.

Binding a Cplusplus Library in the SDK

It is strongly recommended to create a backup copy of the current SDK before proceeding. This step ensures that you still own a copy of the original SDK, in case the SDK gets corrupted during or after the editing process.

Browse to the SDK libraries folder and create the folder OwnCppLibs. The default path of the SDK libraries folder under Windows is C:\XDK-Workbench\SDK\xdk110\Libraries. Create a subfolder Include and put all your header files into it (e.g. CppWrapper.h). Create another subfolder Source and put your archive file into it (e.g. CppWrapper.a). Afterwards, you need to make some changes in the makefiles within the common folder of the SDK. You can find the common folder by navigating to SDK > xdk110 > Common within your Project Explorer using the XDK-Workbench.

Open the file application.mk.

Browse down to the line # Build chain settings and add

CPLUS = $(BCDS_TOOL_CHAIN_PATH)/arm-none-eabi-g++

after the line

CC = $(BCDS_TOOL_CHAIN_PATH)/arm-none-eabi-gcc

in the ifneq block and without the prefix path in the else block.

fig1

This modification will integrate the C++ compiler into the build process of the XDK application, since it is needed to link together C and C++ object files.

Then browse down to the end of BCDS_XDK_EXT_INCLUDES and add the following code snippet to it:

-isystem $(BCDS_LIBRARIES_PATH)/OwnCppLibs/Include \

fig2

This sets the include path for the header file associated to your archive file.

Afterwards, browse down to the line @echo "Creating .out $@" for the debug and release target.

Change the line

@$(CC) $(LDFLAGS_DEBUG) $(BCDS_XDK_APP_OBJECT_FILES_DEBUG) $(BCDS_DEBUG_LIBS_GROUP) $(LIBS) -o $@

to

@$(CPLUS) $(LDFLAGS_DEBUG) $(BCDS_XDK_APP_OBJECT_FILES_DEBUG) $(BCDS_DEBUG_LIBS_GROUP) $(LIBS) -o $@

This will ensure that the C++ compiling process links the object files together and converts them into a single binary file.

fig3

Now, to ensure that your archive file can be built within your applications, open the file Libraries.mk, browse to the end of BCDS_THIRD_PARTY_LIBS and add the following code snippet to it:

$(BCDS_LIBRARIES_PATH)/OwnCppLibs/Source/CppWrapper.a \

If the backslash at the end of the previous line is missing, add one, else this will cause issues.

fig4

Save all changes made and rebuild the SDK.