c++matlabstructurematlab-coder

How to pass structures into re-integrated autogenerated C++ code in Matlab


I am trying to test some code that has been generated from Matlab into C++.

To do this I am attempting to integrate and run the generated C++ code back into Matlab.

Here's the function I am trying to use (in Matlab pre-autogen)

function out = getRotationMatrix(aStruct)

out = aStruct.bank_rad*aStruct.heading_rad+aStruct.pitch_rad;

end

I autogenerate it using this ...

function varargout = AutoGenCode(varargin)
% Here we are attempting to generate a C++ class from a matlab function via a
% hosting function

% initialise
varargout = {};

% create instance of  config object
cfg = coder.config('LIB');
% config options
cfg.MaxIdLength                  = int32(64);
cfg.TargetLang                   = 'C++';
cfg.CppPreserveClasses           = 1;
cfg.EnableCustomReplacementTypes = true;
cfg.ReplacementTypes.uint32      = 'uint32_t';
cfg.CppInterfaceStyle            = 'Methods';
cfg.CppInterfaceClassName        = 'FrameTransformation';
cfg.FilePartitionMethod          = 'MapMFileToCFile'; % or 'MapMFileToCFile' SingleFile
cfg.EnableVariableSizing         = false;
%cfg.PreserveVariableNames        = 'UserNames'; % Worse
%cfg.IncludeInitializeFcn         = true;
cfg.PassStructByReference        = true;

thisStruct.bank_rad = 2.1;
thisStruct.heading_rad = 3.1;
thisStruct.pitch_rad = 3.1;

codegen -config cfg getRotationMatrix -args {thisStruct} -report -preservearraydims -std:c++11

end

To move to another area (\unzipped) I use packNGo

load([pwd,'\codegen\lib\getRotationMatrix\buildInfo.mat'])

packNGo(buildInfo,'packType', 'hierarchical','fileName','portzingbit')

Now when i try to re-integrate it i am using clib

cd 'D:\thoros\Components\Frame Transformation Service\FT_V2\unzippedCode'
clibgen.generateLibraryDefinition('FrameTransformation.h','Libraries',{'getRotationMatrix.lib'})
build(defineFrameTransformation)
addpath('D:\thoros\Components\Frame Transformation Service\FT_V2\unzippedCode\FrameTransformation')

Where I had to define the < SHAPE > parameter in the defineFrameTransformation.mlx manually to be 1

When i try and use the function I cant pass a structure without an error

A = clib.FrameTransformation.FrameTransformation()
thisStruct.bank_rad = 2.1;
thisStruct.heading_rad = 3.1;
thisStruct.pitch_rad = 3.1;
>> A.getRotationMatrix(thisStruct)

I get the following error

Unrecognized method, property, or field 'getRotationMatrix' for class 'clib.FrameTransformation.FrameTransformation'.

The problem disappears if rewrite and regenerate the function to accept non-structure input e.g. double.

By using the summary function i can see that the call to getRotationMatrix should be of type clib.FrameTransformation.struct0_T

However i can't seem to create a variable of this type.

summary(defineFrameTransformation)

MATLAB Interface to FrameTransformation Library

Class clib.FrameTransformation.struct0_T

  No Constructors defined

  No Methods defined

  No Properties defined

Class clib.FrameTransformation.FrameTransformation

  Constructors:
    clib.FrameTransformation.FrameTransformation()
    clib.FrameTransformation.FrameTransformation(clib.FrameTransformation.FrameTransformation)

  Methods:
    double getRotationMatrix(clib.FrameTransformation.struct0_T)

  No Properties defined

So how is one supposed to pass structures to C++ libraries in Matlab ??? what am i doing wrong.

Note Matlab 2020B, windows, Visual studio 2019


Solution

  • Ah, you were so close to the solution :)

    There was a small catch there.

    When you are using clibgen.generateLibraryDefinition() you have to make sure that all the type definition are included in the header file. In your case the definition of struct0_T was presnet inside getRotationMatrix_types.h file.

    So you will have to include both the headers using below command :

    clibgen.generateLibraryDefinition(["FrameTransformation.h","getRotationMatrix_types.h"],"PackageName","mylib",'Libraries',{'getRotationMatrix.lib'})
    

    Now you will have to fill the additional details required in the definition file.

    Once you finish that step, you can use below commands to successfully use the interface

    build(definemylib)
    addpath('\\mathworks\home\dramakan\MLAnswers\CLIB_With_Codegen\ToPort\portzingbit\mylib')
    A = clib.mylib.FrameTransformation
    s = clib.mylib.struct0_T
    s.bank_rad =2.1;
    s.heading_rad =3.1;
    s.pitch_rad=3.1;
    A.getRotationMatrix(s)
    

    I could get below output in R2021b

        >> A.getRotationMatrix(s)
    
    ans =
    
        9.6100
    

    Additionally check if you can use MATLAB Coder MEX instead of doing all these circus. You can call the generated code directly in MATLAB using MEX. You can refer below documentation : https://www.mathworks.com/help/coder/gs/generating-mex-functions-from-matlab-code-at-the-command-line.html