Instantiate an instance of C++ object via MATLAB Coder

2 visualizzazioni (ultimi 30 giorni)
I have an interesting task. I would like to call a GNU Octave interpreter via MATLAB Coder. I have custom C++ source code that initialises and prepares Octave interpreter. My current problem lies in making MATLAB coder aware of the C++ `interpreter` instance. Please find below by current attempt:
function [status] = inter_c() %#coder
%INTER_C Initialises Octave interpreter
% Initialises Octave interpreter
coder.cinclude('/opt/local/include/octave-6.1.0/octave/oct.h');
coder.cinclude('/opt/local/include/octave-6.1.0/octave/interpreter.h');
coder.updateBuildInfo('addSourceFiles', 'inter.cpp');
inter = coder.opaque('octave::interpreter'); % <-- error occurs here
status = 0;
status = coder.ceval('initOctInter', coder.ref(inter));
end
When I try to generate the resulting C++ code with
codegen inter_c -lang:c++ -args {} -report
It crashes with the following error:
??? Variable 'inter' is not fully defined on some execution paths.
I understand, that I need to let MATLAB coder know all the details of the `interpreter` definition, but I don't know, how to do that correctly. I also tried to direct coder to the relevant header file with
inter = coder.opaque('interpreter', 'HeaderFile', '/opt/local/include/octave-6.1.0/octave/interpreter.h');
But the error remains the same.
The contents of custom C++ code in `inter.cpp` are:
#include <iostream>
#include <oct.h>
#include <octave.h>
#include <parse.h>
#include <interpreter.h>
// Initialises Octave interpreter
int initOctInter(interpreter &inter) {
int status = -1;
// Inhibit reading history file
inter.initialize_history(false);
// Set custom load path
inter.initialize_load_path(false);
// Initialise interpreter
inter.initialize();
status = (inter.initialized()) ? 0 : -1;
if (status != 0) {
cerr << "Octave interpreter initialisation failed!" << endl;
}
// Make interpreter ready to execute
status = inter.execute();
if (status != 0) {
cerr << "Creating embedded Octave interpreter failed!" << endl;
}
return status;
}
In C++ this task is achieved as follows:
#include <interpreter.h>
int main(void) {
interpreter inter;
// Initialise Octave interpreter
int status = initOctInter(inter);
if (status == 0) {
// Call compute functions
// ...
// Shutdown Octave interpreter (releases memory)
inter.shutdown();
}
return 0;
}
I would appreciate any help and guidance. If possible, would you please direct me to a relevant example? Thank you!
  12 Commenti
Maksims Abalenkovs
Maksims Abalenkovs il 4 Mar 2021
Modificato: Maksims Abalenkovs il 4 Mar 2021
Here is another iteration of my MATLAB function intended for Coder:
function [status] = inter_c() %#coder
%INTER_C Initialises Octave interpreter
% Initialises Octave interpreter
coder.updateBuildInfo('addCompileFlags', '-I/opt/local/include/octave-6.1.0/octave');
coder.updateBuildInfo('addIncludeFiles', 'oct.h');
coder.updateBuildInfo('addIncludeFiles', 'octave.h');
coder.updateBuildInfo('addIncludeFiles', 'parse.h');
coder.updateBuildInfo('addIncludeFiles', 'interpreter.h');
coder.updateBuildInfo('addLinkObjects', 'liboctave.lib', '/opt/local/lib/octave/6.1.0/', '', true, true);
coder.updateBuildInfo('addLinkObjects', 'liboctinterp.lib', '/opt/local/lib/octave/6.1.0/', '', true, true);
coder.updateBuildInfo('addSourceFiles', 'inter.cpp');
coder.updateBuildInfo('addIncludeFiles', 'inter.h');
coder.cinclude('oct.h');
coder.cinclude('octave.h');
coder.cinclude('parse.h');
coder.cinclude('interpreter.h');
coder.cinclude('inter.h');
inter = coder.opaque('octave::interpreter', 'HeaderFile', '/opt/local/include/octave-6.1.0/octave/interpreter.h');
status = 0;
status = coder.ceval('initOctInter', coder.ref(inter));
end
I would like to pass the Octave intepreter instance called `inter` by reference. Since it is C++ the `initOctInter` signature is:
#include <octave.h>
#include <interpreter.h>
using namespace octave;
int initOctInter(interpreter &inter);
// @eof inter.h
Please see the StackOverflow answer of Sean Ramey for an example.
My new attempt still crashes with the following error:
codegen inter_c -lang:c++ -args {} -report
??? Variable 'inter' is not fully defined on some execution paths.
For completeness please find below the contents of `inter.cpp` file and `test_inter.cpp` (native C++ code for calling Octave interpreter):
#include <iostream>
#include <oct.h>
#include <octave.h>
#include <parse.h>
#include <interpreter.h>
using namespace std;
using namespace octave;
// Initialises Octave interpreter
int initOctInter(interpreter &inter) {
int status = -1;
try {
status = inter.execute();
}
catch (const exit_exception& ex) {
}
catch (const execution_exception&) {
}
return status;
}
// @eof inter.cpp
C++ source code of `test_inter.cpp`:
#include <iostream>
#include <oct.h>
#include <octave.h>
#include <parse.h>
#include <interpreter.h>
#include "inter.h"
using namespace std;
using namespace octave;
int main(int argc, char *argv[]) {
interpreter inter;
int status = initOctInter(inter);
cout << "status:" << status << endl;
// Shutdown interpreter
inter.shutdown();
return 0;
}
// @eof test_inter.cpp
Maksims Abalenkovs
Maksims Abalenkovs il 4 Mar 2021
Changing `coder.ref(inter)` to `coder.wref(inter)` makes Coder crash with another error:
inter_c.cpp:31:10: error: no matching function for call to 'initOctInter'
return initOctInter(&inter);
^~~~~~~~~~~~
/Users/mabalenk/repo/git/alc/rascal/oct/inter.h:6:5: note: candidate function not viable: no known conversion from 'octave::interpreter *' to 'octave::interpreter &' for 1st argument; remove &
int initOctInter(interpreter &inter);
But I don't believe this is a correct approach.

Accedi per commentare.

Risposte (2)

Shadaab Siddiqie
Shadaab Siddiqie il 4 Mar 2021
From my understanding you want to Instantiate an instance of C++ object. Refer similar answer which might help you.
  1 Commento
Maksims Abalenkovs
Maksims Abalenkovs il 4 Mar 2021
I was hoping to avoid writing custom wrappers to C++ functions. I wanted to call basic interface functions similar to `initOctInt()` and pass them the instance of an object and let native C++ deal with the object methods. But it seems I will still have to go that route. I feel it is too complicated for an average MATLAB user. Time to study your `person` example.

Accedi per commentare.


Darshan Ramakant Bhat
Darshan Ramakant Bhat il 4 Mar 2021
I tried to solve this issue by creating the similar example.
I have mocked up some of the files using my own definition of the interpreter. Please go through the attached code.
I guess you were almost there using coder.wref(), only thing was you need to change your interface to take pointer (*) not as referece (&).
Hope this will be helpful for you.
codegen inter_c -lang:c++ -args {} -report
  8 Commenti
Darshan Ramakant Bhat
Darshan Ramakant Bhat il 5 Mar 2021
The problem looks to be that both the definitions are reachable. I cannot think of a good solution unless you rename the definition in ov.h
Maksims Abalenkovs
Maksims Abalenkovs il 8 Mar 2021
Modificato: Maksims Abalenkovs il 8 Mar 2021
Thank you @Darshan Ramakant Bhat for your suggestion. But this is a very intrusive solution, that I would like to avoid for now. I made an inquiry about it on the GNU Octave mailing list. Let's see, what they respond. Otherwise, we will have to take this route ;)

Accedi per commentare.

Prodotti


Release

R2020b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by