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

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

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.

Related

Using the C++ libraries (clibgen) in Matlab simulink

I used the clibgen.generateLibraryDefinition to generate the Matlab interface for C++ libraries.
I applied it in a Matlab function and it worked well.
However, when I tried to use it in the Matlab Simulink with the Matlab function block, it gave errors " Attempt to extract field 'i' from 'mxArray'. "
Is that anything I'm missing to add in the Simulink?
Thanks!
function cube = fcn(size_x, size_y, range_x_min, range_x_max, ...
range_y_min, range_y_max, power, ...
transmitter_height, receiver_height, ...
transmitter_position, frequency)
coder.extrinsic('clib.Wave.Wave.EMWave');
coder.extrinsic('clib.Wave.Wave.Index');
coder.extrinsic('clib.Wave.Wave.Vec2d');
coder.extrinsic('clib.Wave.Wave.Terrain');
coder.extrinsic('clib.Wave.Wave.Transimtter');
coder.extrinsic('clib.Wave.Wave.Source');
coder.extrinsic('clib.Wave.Wave.Cube');
coder.extrinsic('clib.Wave.Wave.Terrain');
coder.extrinsic('clib.Wave.Wave.Ray');
index = clib.Wave.Wave.Index;
radio_wave = clib.Wave.Wave.EMWave;
terrain = clib.Wave.Wave.Terrain(200,200,range_x_min,range_y_min,range_x_max,range_y_max);
index.i = 1;
index.j = 1;
% radio_wave.transmitter.set_power(1000);
% radio_wave.transmitter.set_height(150.0);
% radio_wave.transmitter.set_number_of_discrete_rays(7200);
%code.varsize('cube',[1 size_x],[1 size_y]);
cube = zeros(200,200);
end

C++ | How to remove the DataSource from a combobox?

I'm writing a windows forms application in visual studio with c++ and CLR.
And now, i got the following problem:
I read in a file and save all the important informations in a vector.
With a second step, i convert all items to a CLR array and set this array as DataSource.
array<System::String^>^ PREDEFINED = gcnew array <System::String^>(OP->CIS_Values[OP->selectedCIS]->PREDEFINED_order.size());
for (int i = 0; i < OP->CIS_Values[OP->selectedCIS]->PREDEFINED_order.size(); i++) {
PREDEFINED[i] = msclr::interop::marshal_as<System::String^>(OP->CIS_Values[OP->selectedCIS]->PREDEFINED_order[i]);
}
this->comboBox_header_predefinedtypes->DataSource = PREDEFINED;
this->comboBox_header_predefinedtypes->SelectedIndex = -1;
delete PREDEFINED;
After setting the DataSource, it must be possible to remove it. In C# i can do this with
comboBox.DataSource = null;
but how does it work in C++?
I tried the following cases:
comboBox_header_predefinedtypes->DataSource = NULL;
comboBox_header_predefinedtypes->DataSource = 0;
comboBox_header_predefinedtypes->DataSource = -1;
comboBox_header_predefinedtypes->DataBindings->Clear();
comboBox_header_predefinedtypes->Items->Clear();
I tried it with DataBindings before and after DataSource, but i always get the same exception:
System.ArgumentException: "The complex DataBinding accepts as a data source either IList or IListSource"
How can i fix this issue ?
Thx for help.
In C++ CLR you only need to write:
comboBox_header_predefinedtypes->DataSource = nullptr;
and you don't need to write
comboBox_header_predefinedtypes->Items->Clear();
after removing the DateSource to delete the items.

Using decision within a java delegate

I am trying to evaluate a decision inside a camunda java delegate that I created. Following is the code that I am using. Upon executing the delegate( which runs fine without the DMN part), I get an error stating:
java.lang.NoClassDefFoundError: de/odysseus/el/util/SimpleContext"
I am using gradle and have added the following to my .build :
compile 'org.camunda.bpm.dmn:camunda-engine-dmn' ,
'org.camunda.bpm.dmn:camunda-engine-feel-juel:7.5.0-alpha2' ,
'de.odysseus.juel:juel-spi:2.2.7',
'de.odysseus.juel:juel-api:2.2.7' ,
'de.odysseus.juel:juel-impl:2.2.7'
Any suggestion how can I fix this error up? Thanks.
DMN Code:
DmnEngine dmnEngine = DmnEngineConfiguration.createDefaultDmnEngineConfiguration().buildEngine();
// read the DMN XML file as input stream
InputStream inputStream = CheckDatafileExistsExecutor.class.getResourceAsStream("decision1.xml");
// parse the DMN decision from the input stream
DmnDecision decision = dmnEngine.parseDecision("Decision_13nychf", inputStream);
//accessing the input variables
VariableMap variables = Variables.fromMap((Map<String, Object>) decision);
// evaluate the decision table with the input variables
DmnDecisionTableResult result = dmnEngine.evaluateDecisionTable(decision, variables);
int size = result.size();
DmnDecisionRuleResult ruleResult = result.get(0);
Remove all your dependencies and add only compile group: 'org.camunda.bpm.dmn', name: 'camunda-engine-dmn', version: '7.6.0'
You can try also menskis example, but change the camunda-engine-dmn to 7.6.0
and
DmnDecisionTableResult results = dmnEngine.evaluateDecisionTable("decision", "Example.dmn", variables);
to
InputStream fileAsStream = IoUtil.fileAsStream("Example.dmn");
DmnDecisionTableResult results = dmnEngine.evaluateDecisionTable("decision", fileAsStream, variables);
You can use delegate service for decision evaluation based on key or Id,
eg:-
public void execute(DelegateExecution delegateExecution) throws Exception{
DecisionService decisionService = delegateExecution.getProcessEngineServices().getDecisionService();
decisionService.evaluateDecisionByKey(dmnToInvoke).variables(delegateExecution.get Variables()).evaluate();
}

How to get the screen size with C++ builder (Firemonkey)

I know it is a stupid question, but when changing visual libraries I found a "throuble" with FMX...
My problem is: I need to do my own border, so I set the propriety to Border Style:"None", but the application runs in full screen, also covering the windows toolbar, so I would like a way to resize the application form according to the screen eg.:
mainForm->Height = Screen->Height - 10;
It is possible using VCL, but are there any way to do it using FMX library?
The maximum I conquested with FMX is (I don't know how does it returns values, and the kind of values):
Screen->Size(); // TSize
I've also conquested it now, but I have compiler error:
TSize* Tamanho = new TSize;
Tamanho = Screen->Size();
frmPrincipal->Width = Tamanho->Width;
frmPrincipal->Height = Tamanho->Height - 10;
Error:"E2034 Cannot covert 'TSize' to 'TSize*'"
Finally I've tried to put it on frmPrincipal.h, but the same error:
TSize *Tamanho;
PS.: Other possible solutions to solve the "main problem" are acceptable...
Thanks a LOT!
TScreen::Size() return an actual instance of the TSize struct, not a TSize* pointer. You need to change your code accordingly:
TSize Tamanho = Screen->Size();
frmPrincipal->Width = Tamanho.Width;
frmPrincipal->Height = Tamanho.Height - 10;
Alternatively, you can use FMX's Platform Services framework to access the IFMXScreenService interface directly (this is what TScreen::Size() uses internally):
_di_IInterface Intf;
if (TPlatformServices::Current->SupportsPlatformService(__uuidof(IFMXScreenService), Intf))
{
_di_IFMXScreenService Svc = Intf;
TPoint size = Svc->GetScreenSize().Round();
frmPrincipal->Width = size.X;
frmPrincipal->Height = size.Y - 10;
}

How to access file given to cilly in my CIL module

I have added a new feature to CIL(C Intermediate Language). I am able to execute my new module using
$cilly --dotestmodule --save-temps -D HAPPY_MOOD -o test test.c
Now, in my testmodule, I want to call Cfg.computeFileCFG for test.c file. But I don't know how to access test.c file in my module.
I tried using Cil.file. but it says "Unbound value Cil.file".
my code:
open Pretty
open Cfg
open Cil
module RD = Reachingdefs
let () = Cfg.computeFileCFG Cil.file
let rec fact n = if n < 2 then 1 else n * fact(n-1)
let doIt n = fact n
let feature : featureDescr =
{ fd_name = "testmodule";
fd_enabled = ref false;
fd_description = "simple test 1240";
fd_extraopt = [];
fd_doit = (function (f: file) -> ignore (doIt 10));
fd_post_check = true;
}
please tell me how to compute the Cfg for test.c file.
I am not a CIL expert, but here are a few remarks:
the CIL online documentation states that Cil.file is an Ocaml type. Passing a type as an argument to a function is probably not what you want to do here;
it seems like the fd_doit function in your feature descriptor takes the file you are looking to process as its argument f;
according to the Cilly manual, the type of f is Cil.file. Conveniently, this seems to be the type of the argument required by the function computeFileCFG.
Hopefully you can take it from here. Good luck!