主要内容

Generate C++ Executable for Entry-Point System Object in a Namespace (Tech Preview)

Since R2026a

This example shows how to use a System object™ in a namespace as an entry point for C++ code generation. The code generator produces an C++ class that you can access directly from your external C++ code. You then create a C++ executable that uses the generated C++ class.

Note

Using a MATLAB® class as an entry point for code generation is a tech preview. This feature is in active development and may change between the tech preview and the general release. The primary purpose of the tech preview is to solicit feedback from users. To enable the feature, enter enableCodegenForEntryPointClasses at the command line before calling the codegen function or creating a coder.Type object in a MATLAB session. To provide feedback, email the development team or participate in a survey.

Enable Feature and Create MATLAB Class

First, enable code generation for entry-point classes.

enableCodegenForEntryPointClasses
=== Code generation for entry-point classes is ENABLED ===

This example uses the System object MyCounter. The public MyCounter class constructor method defines a MyCounter object with a step size specified by the public property StepSize. The default value of StepSize is 1. The MyCounter class implements the protected method stepImpl, which increments the counter. The System object step method invokes the stepImpl method. The MyCounter class also implements the protected setupImpl and resetImpl methods, which respectively initialize and reset the counter. Save the MyCounter definition in the namespace +MyNamespace.

classdef MyCounter < matlab.System
    properties
        StepSize = 1
    end

    properties (DiscreteState)
        Count
    end

    methods
        function obj = MyCounter(stepVal)
            if nargin > 0
                obj.StepSize = stepVal;
            end
        end
    end

    methods (Access = protected)
        function setupImpl(obj)
            obj.Count = 0;
        end

        function y = stepImpl(obj)
            obj.Count = obj.Count + obj.StepSize;
            y = obj.Count;
        end

        function resetImpl(obj)
            obj.Count = 0;
        end
    end
end

Define coder.ClassSignature Object

Define a coder.ClassSignature object by using the name of the namespace and the MyCounter class. MATLAB creates a coder.ClassSignature object that includes the name of the namespace.

classSig = coder.ClassSignature("MyNamespace.MyCounter")
classSig = 

coder.ClassSignature
  1×1 MyNamespace.MyCounter
      TypeName: "MyCounter"
    Properties: struct with no fields.
   Methods: dictionary (string --> cell) with no entries.

Add the public constructor method to the classSig object by using the addMethod method. Do not include the namespace in the name of the method, because MATLAB does not store class methods inside namespaces. Specify that the constructor method is polymorphic and accepts one or zero arguments.

addMethod(classSig,"MyCounter",{0});
addMethod(classSig,"MyCounter",{})
ans = 

coder.ClassSignature
  1×1 MyNamespace.MyCounter
      TypeName: "MyCounter"
    Properties: struct with no fields.
       Methods:
         MyCounter:
           (1) Args: {1×1 double}
           (2) Args: {}

The code generator creates two coder.FunctionSignature objects that represent the two signatures of the MyCounter method and adds these methods to the class signature object.

Add the System object step method to the coder.ClassSignature object. Because step can return a variable number of outputs, specify the Nargout name-value argument when you call addMethod.

addMethod(classSig,"step",{classSig},Nargout = 1)
ans = 

coder.ClassSignature
  1×1 MyNamespace.MyCounter
      TypeName: "MyCounter"
    Properties: struct with no fields.
       Methods:
         MyCounter:
           (1)    Args: {1×1 double}
           (2)    Args: {}
         step:
                  Args: {1×1 this}
               Nargout: 1

Specify C++ Namespace for Generated Code

You can use the code configuration settings to control how the code generator creates namespaces for the code it generates. See Organize Generated C++ Code into Namespaces.

By default, the code generator produces C++ namespaces for the namespaces in the MATLAB code. In this example, it stores the code it generates for the user-written MATLAB code in the C++ namespace MyNamespace. To further control how the code generator partitions the generated C++ code into namespaces, create a code configuration object for a static library and modify these settings:

  • To generate C++ code, set the TargetLang property to "C++". See Language.

  • To instruct the code generator to contain the C++ code it generates in the namespace allCode, set the CppNamespace property to "allCode". See C++ namespace.

  • To instruct the code generator to contain the code it generates for MathWorks® code in the namespace notMyCode, set the CppNamespaceForMathworksCode property to "notMyCode". See Namespace for MathWorks code.

cfg = coder.config("lib");
cfg.TargetLang = "C++";
cfg.CppNamespace = "allCode";
cfg.CppNamespaceForMathworksCode = "notMyCode";

Generate and Inspect Standalone C++ Code

Generate a C++ static library for the MyCounter class by passing the classSig object to the codegen command. Use the -class option to specify the class object, and use the -config option to specify the code configuration object.

codegen -config cfg -class classSig
Code generation successful.

Inspect the definition of the MyCounter class in the generated C++ header file MyNamespace_MyCounter.h.

// Type Definitions
namespace allCode {
namespace MyNamespace {
class MyCounter {
public:
  void init(double stepVal);
  void init();
  double step();
  explicit MyCounter(double stepVal);
  explicit MyCounter(user_construct_tag_t tag);
  MyCounter();
  ~MyCounter();

private:
  void System();

public:
  boolean_T tunablePropertyChanged;
  int isInitialized;
  boolean_T TunablePropsChanged;
  double StepSize;
  double Count;

private:
  boolean_T isSetupComplete;
};

The definition of the MyCounter class is in the namespace MyNamespace, which is in the namespace allCode. The code generator produces three constructor methods:

  • explicit MyCounter(double stepVal), which maps to the constructor that accepts a double value.

  • explicit MyCounter(user_construct_tag_t tag), which maps to the constructor that accepts zero arguments.

  • MyCounter(), which is the non-initializing constructor.

The external C++ application can interact directly with the public MyCounter constructors and with the public property StepSize. The init methods and the non-initializing constructor are internal methods. Because these methods may change in the future, do not use them in your custom C++ code.

The System method performs operations internal to the generated System object class. The System method uses the public state members tunablePropertyChanged, isInitialized, and TunablePropsChanged to manipulate instances of the C++ class.

Inspect the definition of the MyCounter::init method in the file MyNamespace_MyCounter.cpp.

void MyCounter::init(double stepVal)
{
  System();
  notMyCode::matlab::b_system::coder::SystemProp::matlabCodegenNotifyAnyProp(
      this);
  StepSize = stepVal;
}

The init method uses the method matlabCodegenNotifyAnyProp. Because the code generator produces the C++ code for this method from MathWorks code, the code generator defines the matlabCodegenNotifyAnyProp method in the C++ namespace notMyCode.

Create C++ main Function

Create a C++ main function that uses the generated C++ class. When you generate code for an entry-point class, the code generator does not produce an example main function.

In this example, the main function creates two instances of the MyNamespace::MyCounter class:

  • It uses the constructor that accepts a double value to create countStep3, which has a step size of three.

  • It uses the constructor that accepts the user_construct_tag_t tag to create countStepD, which has the default step size of one.

The main function increments each counter twice and displays the results. Save this file in the working directory as main_MyCounter.cpp.

#include "MyNamespace_MyCounter.h"
#include <iostream>

int main(void) {
    using namespace allCode;
    MyNamespace::MyCounter countStep3{3};
    MyNamespace::MyCounter countStepD{user_construct_tag_t{}};

    std::cout << "MyCounter with StepSize: " << countStep3.StepSize << std::endl;;
    std::cout << "Increment once: " << countStep3.step() << std::endl;
    std::cout << "Increment twice: " << countStep3.step() << std::endl;
   
    std::cout << "MyCounter with StepSize: " << countStepD.StepSize << std::endl;;
    std::cout << "Increment once: " << countStepD.step() << std::endl;
    std::cout << "Increment twice: " << countStepD.step() << std::endl;

    return 0;
}

Generate C++ Executable

Generate a C++ executable by using the codegen command. To generate executable code, set the OutputType property of the configuration object to "EXE". See Build type.

cfg.OutputType = "EXE";

Instruct the codegen command to include the main_MyCounter.cpp source code file by specifying the file name on the command line. The code generator creates the MyNamespace_MyCounter executable in the working folder.

codegen -config cfg -class classSig main_MyCounter.cpp;
Code generation successful.

To run the executable in MATLAB, use the system command. Use the ispc function to select the appropriate system command.

if ispc
    system("MyNamespace_MyCounter.exe")
else
    system("./MyNamespace_MyCounter")
end
MyCounter with StepSize: 3 
Increment once: 3 
Increment twice: 6 
MyCounter with StepSize: 1 
Increment once: 1 
Increment twice: 2 

ans =

     0

See Also

| | |

Topics