Main Content

Integrate Multiple Generated C++ Code Projects

This example shows how to integrate two different generated C++ code projects into a single, larger project.

Your generated code projects might have similar function names, but have different settings, parameters, or functionality. Generate code with namespaces to aid in integrating different projects that share the same names. Namespaces can also improve code readability.

Generate C++ Code for a MATLAB® Algorithm

Consider a simple MATLAB function that returns a gravitational constant. The value of the gravitational constant is derived from a global variable.

type getGravityConst.m
function c = getGravityConst %#codegen
global g
c = g;

Suppose that you want to generate code for getGravityConst that models scenarios for the Moon and for the Earth. Generate two separate code projects with the same entry-point function. Specify a different global value, and hence, gravitational constant, for each project.

Create a code generation configuration object. Specify:

  • DLL build type.

  • C++ target language.

  • The name of the orbital body as the namespace.

  • #pragma once style #include guards.

  • Packaging of the generated code files into a .zip file by calling the packNGo function.

cfg = coder.config('dll');
cfg.TargetLang = "C++";
cfg.CppNamespace = 'moon';
cfg.HeaderGuardStyle = "UsePragmaOnce";
cfg.PostCodeGenCommand = 'packNGo(buildInfo)';

Generate code for getGravityConst to model the Moon:

  • By using the previously defined configuration object.

  • With a code generation report.

  • Such that the code returns the Moon's value of the gravitational constant in units of m/s^2.

  • In an output folder called projectMoon.

  • With output binaries called getGravityConstMoon.

codegen getGravityConst -config cfg -report -globals {'g', -1.62} ...
    -d projectMoon -o getGravityConstMoon
Code generation successful: View report

To generate code for getGravityConst that models the earth, first modify the:

  • Namespace name

  • Gravitational constant

  • Output file name

  • Output folder name

cfg = coder.config('dll');
cfg.TargetLang = "C++";
cfg.CppNamespace = 'earth';
cfg.HeaderGuardStyle = "UsePragmaOnce";
cfg.PostCodeGenCommand = 'packNGo(buildInfo)';

codegen getGravityConst -config cfg -report -globals {'g', -9.81} ...
    -d projectEarth -o getGravityConstEarth
Code generation successful: View report

Project Integration Scenario: Planetary Modeling

Suppose that you want to design a larger project that performs planetary modeling and computes quantities such as the flight times of falling objects. The flight time depends on the gravitational constant for each planet and the initial height of the object. You want to use the generated code functions for getGravityConst in this larger project.

Determine the Platform-Dependent File Extensions

The generated dynamic libraries have different extensions on different platforms. This code determines the correct extensions for your platform.

dllext = '';
libext = '';
if ismac
    dllext = '.dylib';
    libext = dllext;
elseif isunix
    dllext = '.so';
    libext = dllext;
elseif ispc
    dllext = '.dll';
    libext = '.lib';
    disp('Platform not supported')

Write a Main File That Uses the Generated Code Projects

In the general case, you integrate different projects by writing or modifying a main file to call each of the projects' functions. By using namespaces, you can distinguish the generated functions for each project, even though the function names are the same.

For an example of how to write a main file that uses the generated C++ code for both projects, see the attached file main_planetSim.cpp. To build an executable or binary from the main file, you must specify or provide the following to the build tools (compiler, linker, and/or IDE) and their correct paths:

  • Header files for any called functions.

  • On Windows platforms, import libraries (.lib files).

  • Dynamic libraries (.dll, .so and .dylib files).

  • Include directories for other generated source and include files.

The .zip files that the packNGo command creates during code generation contain the generated code files. Unpack the zip files to folders in your build directory or build environment. You must also make your dynamic libraries accessible to the executable, for example, by moving the generated dynamic libraries to the same folder as the executable.

Write a MATLAB Function that Integrates the Two Projects

As an alternative to writing a main file by hand, you can also integrate two projects into a third generated code project by using the coder.ceval function. The coder.ceval function enables you to call external C/C++ code from generated C/C++ code.

The file planetSim.m shows how to use coder.ceval and associated build configuration functions to integrate the generated projects into the larger project.

function [t_m, t_e] = planetSim %#codegen
% Example function that integrates generated code projects with namespaces
d = 10; 
g = 0;

% Add #include statements for external function names

% Call external functions & do computations
g = coder.ceval('moon::getGravityConst');
t_m = timeToDrop(d,g);

g = coder.ceval('earth::getGravityConst');
t_e = timeToDrop(d,g);

function t = timeToDrop(d,g)
t = sqrt(2*d/(-g));

Generate MEX code for the planetSim function:

linkObjectMoon = ['projectMoon/getGravityConstMoon' libext];
linkObjectEarth = ['projectEarth/getGravityConstEarth' libext];

cfg = coder.config('mex');
cfg.TargetLang = "C++";
Code generation successful: View report

Test the Generated MEX Function

Use the MEX function to test the generated code in the MATLAB environment. The MEX function must have access to the generated link libraries. Move the link libraries to the current directory and call the MEX function.

copyfile(['projectMoon/getGravityConstMoon' dllext]);
copyfile(['projectEarth/getGravityConstEarth' dllext]);

[t_m, t_e] = planetSim_mex
t_m = 3.5136
t_e = 1.4278

The output shows the flight times for the falling object on the Moon and on the Earth.

See Also

| | | | |

Related Topics