Main Content

External Code Integration of Libraries and C/C++ Code with Simulink Real-Time Models

Considerations for Integrating Third-Party Libraries and External Code into Simulink Real-Time

Developers integrating C/C++ code with Simulink Real-Time applications notice some differences when they migrate the code that they integrated with Simulink Real-Time applications from release R2020a and previous to R2020b and later. These differences include:

  • In release R2020a and previous, the On-Time RTOS on the target computer shared some libraries and system calls with Windows®. In release R2020b and later, the QNX® Neutrino® RTOS on the target computer does not share Windows-specific libraries or system calls.

  • In release R2020a and previous, developers could use Microsoft® Visual Studio® to compile libraries to integrate with Simulink Real-Time applications. In release R2020b and later, the Microsoft Visual Studio compiler cannot be used for this purpose. You can configure Microsoft Visual Studio to use the QNX Neutrino compiler from the Simulink Real-Time target support package.

  • In R2020b and later, developers use cross-compiling to produce libraries on their development computer for deployment to their target computer.

Value of Upgrading Your C/C++ Code for Integration into Simulink Real-Time

By updating your C/C++ code for integration into your Simulink Real-Time application, you gain these benefits:

  • Leverage the QNX Neutrino 64-bit and POSIX® compatible RTOS

  • Code directly in C++ or wrap your legacy C code

  • Use the code editor of your choice.

    For instance, customizing Visual Studio Code with the source files and shipped QCC compiler from the Simulink Real-Time Target Support Package provides a similar experience to a full IDE

  • Leverage the precompiled QNX Neutrino libraries and headers that are included in Simulink Real-Time to extend the functionality of your real-time application

  • Integrate any C/C++ application based on modern build and package software such as CMake

Approaches for C/C++ Code Integration into Simulink Real-Time

There are advantages and disadvantages to each of these external code integration approaches.

Approach 1: Directly Call C/C++ Code. In this approach, you ​use C Caller or C Function blocks in the model. For more information, see Integrate External C Algorithms Using C Function Blocks.​

Approach 2: Build, link, and use static libraries (.a files)​

  • Advantages​: All required files are packed in the real-time application MLDATX file. In this approach, ​there is no need to install libraries on the target. And, this approach lets you ​protect your intellectual property.​

  • Disadvantages​: This approach is non-modular. A change in the library requires re-building the whole real-time application​. Also, this approach tends to produce larger real-time application MLDATX files.​

Approach 3: Build, deploy and use shared objects (.so files)​

  • Advantages​: This approach is modular. The real-time application and shared object can be built independently​. Also, this approach tends to produce smaller real-time application MLDATX files. And this approach lets you protect your intellectual property.​

  • Disadvantages: ​In this approach, you need to access the target computer file system before running the real-time application and install (copy) the shared objects​ to any of the common lib paths on the target computers..

Build Libraries from Source Code for Simulink Real-Time

To integrate external code in a real-time application, the most flexible approaches are to build static libraries or shared objects from source code. The factors that make these approaches flexible are:

  • The library build workflow is similar to the workflow used by most developers for release R2020a and previous releases. In those releases, the library build workflow for the target computer On-Time RTOS produced static libraries built with Microsoft Visual Studio and produced .lib files.

  • Better usability when working with complex C++ projects with many dependencies and source code files.

  • S-Functions offer better granularity when handling third party libraries in Simulink and enable the flexibility to use the same S-Function source code with different platforms, including simulation on desktop in different OS and deployment and function in real-time on a target computer.

Cross-compiling is compiling a library for target OS (for example, QNX Neutrino RTOS) on a development OS (for example, Windows). Some cross-compiling considerations for Simulink Real-Time:

  • The choice of development environment is important. Many modern C++ projects use the CMake build environment. For more information, see the CMake website.

  • Extensibility of development environment is important. For example, it is a common practice to extend most common CMake support for the QNX Neutrino RTOS by leveraging similarities with the UNIX® OS and its POSIX compatibility.

  • In your libraries, remember to save cross-compiling libraries, including dependencies that may be already included in the Simulink Real-Time Target Support Package. These libraries can be linked to other C++ projects..

The recommended workflow for integration of complex C++ applications into Simulink Real-Time is:

  1. Start from a C++ project with CMake as the build environment.​

  2. Set the dependencies, such as headers and libraries, in your Simulink model.​

  3. On the development computer, cross-compile libraries for the QNX Neutrino RTOS on the target computer.​

  4. Create an S-Function, for instance using the S-Function Builder block or a handwritten C-MEX S-Function, as the main function that calls the C++ functions defined in the header files and implemented in the compiled libraries for the QNX Neutrino RTOS​.

  5. Build the real-time application. ​

  6. By using SSH or FTP, copy your cross-compiled libraries to a location on the target computer where they can be found and loaded at runtime. The recommended locations are /lib, /usr/lib, or /usr/local/lib.

  7. Load and run the real-time application.

External Code Integration for S-Functions and Simulink Real-Time

When you include static libraries or shared objects in S-Functions for external code integration with a real-time application, there are some tips that can ease your development.

When building from Simulink, you should:

  • Use rtwmakecfg.m and makeInfo object to map libraries and header files. For more information, see Use rtwmakecfg.m API to Customize Generated Makefiles.

    function makeInfo = rtwmakecfg​
    proj = currentProject;​
    rootPath = proj.RootFolder;​
    makeInfo.linkLibsObjs = {};​
    sysTarget = get_param(bdroot, 'RTWSystemTargetFile');​
    switch sysTarget​
        case 'slrealtime.tlc'​
            makeInfo.includePath = '<includePath>';​
            makeInfo.linkLibsObjs{end+1} = '<libraryPath>';​
        otherwise​
            error('No rtwmakecfg found for %s target file', sysTarget);​
    endend
  • Enable linking for different target files.

  • Use macros such as SIMULINK_REAL_TIME in your source code to add lines at compile time for real-time simulation. SIMULINK_REAL_TIME is useful to wrap the LOG function calls

When cross compiling, use macros such as __unix__ and __QNXNTO__ in your source code to add lines at compile time.

Hello World! External Code Integration for Simulink Real-Time

This example shows how to use an S-Function Builder block for external code integration. The example adds a hello message to the system log.

Before running this example, install the Simulink Real-Time Target Support Package. The support package includes the tools that compile code that runs on the target computer.

Open the Model

Use the Open Model button to open the helloworld.slx model.

open_system('slrt_ex_helloworld_sfunbuilder');

Open the S-Function Block

Double-click the helloworld-sfun S-Function block. The S-Function Builder opens and displays the S-Function code.

/* Includes_BEGIN */
#ifdef SIMULINK_REAL_TIME
#include "slrt_log.hpp"
#endif
/* Includes_END */
/* Externs_BEGIN */
/* extern double func(double a); */
/* Externs_END */
void helloworld_sfun_Start_wrapper(SimStruct *S)
{
/* Start_BEGIN */
/* Start_END */
}
void helloworld_sfun_Outputs_wrapper(const real_T *u0,
                                     real_T *y0,
                                     SimStruct *S)
{
/* Output_BEGIN */
// Create custom message
static char hellomsg[100];
sprintf(hellomsg,"Hello World! t=%f \n",*u0);
// Use macros for platform dependent code
#ifdef SIMULINK_REAL_TIME
slrealtime::log_info(hellomsg);
#else
ssPrintf(hellomsg);
#endif
// Generic platform independent code
*y0 = *u0;
/* Output_END */
}
void helloworld_sfun_Terminate_wrapper(SimStruct *S)
{
/* Terminate_BEGIN */
/*
 * Custom Terminate code goes here.
 */
/* Terminate_END */
}

Build Model and Run Real-Time Application

Before building the model, you can run the model on your desktop and view the output message in the Simulink Real-Time system log viewer.

When you are ready to build the model, on the Simulink Editor Real-Time tab, connect to the target computer and click Run on Target. Or, in the MATLAB Command Window, type:

tg = slrealtime;
connect(tg);
model = 'slrt_ex_helloworld_sfunbuilder';
evalc('slbuild(model)');
load(tg,model);
start(tg);
pause(20);
stop(tg);

View Message in Status Log

Open the target computer status log and view the Hello World! message. On the Simulink Editor Real-Time tab, select Prepare > SLRT Explorer. Then, select the System Log Viewer tab. Or, in the MATLAB Command Window, type:

slrtLogViewer;

The viewer shows the Hello World! messages in the system log.

Close All

bdclose('all');

Additional C/C++ Project for Simulink Real-Time

The eCAL Toolbox for Simulink project on MathWorks GitHub shows complete external code integration with Simulink Real-Time, including S-Function wrappers, rtwmakecfg customization, and shared object compilation. You also can simulate this example on your development computer.

Related Topics

External Websites