简体   繁体   中英

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 eg 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

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

If you have Embedded Coder (the line cfg.ReplacementTypes.uint32 = 'uint32_t' suggests you do), then you can use SIL to do what you're proposing with just a few lines of code:

cfg.VerificationMode = 'SIL';

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

codegen ...

% Now test the generated code. This calls your actual generated code
% and automatically does all of the necessary data conversion. The code
% is run in a separate process and outputs are returned back
% to MATLAB
getRotationMatrix_sil(thisStruct)

More info is in the doc . If you have tests / scripts already exercising your MATLAB code, you can reuse those with SIL by checking out coder.runTest and the codegen -test option.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM