How to convert a matlab::me​x::Argumen​tList to a custom C++-Type and vice versa

조회 수: 34 (최근 30일)
Friedrich
Friedrich 2024년 10월 24일 10:30
댓글: Walter Roberson 2024년 10월 25일 18:59
I have some C++ source code that is accessable in Simulink with the help of the Legacy Code Tool. I want the same C++ code also be callable from Matlab. My research led me to the "C++ MEX API" with which I am struggeling. If there is another simpler approach, please let me know.
My problem is that I need to wrap the arguments of the operator method
void operator()(matlab::mex::ArgumentList outputs, matlab::mex::ArgumentList inputs)
into some user-defined C++ structs such that I can call my custom code
void myCode(userStruct1 &in, userStruct2 &out)
For simple inputs of operator() I managed to loop through "inputs" and the containing matlab::data::Array. I then assigned these values into my userStruct1 object. I find this procedure tedious but I can live with that. If there's an easier way to convert from matlab::data::ArgumentList to userStruct1 please let me know.
My problem, however, is the other way around. Assume myCode is called and the results are written in the userStruct2 object. How do I pass these results to "outputs"?
  댓글 수: 1
Friedrich
Friedrich 2024년 10월 24일 10:44
편집: Friedrich 2024년 10월 24일 11:42
Let's assume userStruct2 is:
struct userStruct2 {
std::vector<double> a;
std::vector<double> b;
double c;
bool d;
char e[10];
userStruct2() : a(3), b(5) {}
};

댓글을 달려면 로그인하십시오.

채택된 답변

埃博拉酱
埃博拉酱 2024년 10월 25일 15:43
편집: 埃博拉酱 2024년 10월 25일 15:56
Obviously we can't think of any simpler way to convert to userStruct1 unless you tell us how you defined it.
For userStruct2, your code is risky because MATLAB chars are UTF16 encoded while C++ chars are usually UTF8 encoded. MATLAB does not do encoding conversions, so if your string contains non-ASCII characters it will be garbled. On Windows you can consider:
#include <Windows.h>
import std;
using namespace matlab::data;
ArrayFactory factory;
template<typename T>
TypedArray<T> VectorToArray(const std::vector<T>& vec)
{
TypedArray<T> arr = factory.createArray<T>({ vec.size() });
std::copy(vec.cbegin(), vec.cend(), arr.begin());
return arr;
}
CharArray CppCharToMatlab(const char* Input, size_t Length)
{
//This function does encoding conversion. You can implement it with any other libraries if you don't have Windows SDK.
buffer_ptr_t<char16_t> Buffer = factory.createBuffer<char16_t>(Length + 1);
Length = MultiByteToWideChar(CP_UTF8, 0, Input, Length, (wchar_t*)Buffer.get(), Length + 1);
return factory.createArrayFromBuffer({ 1,Length }, std::move(Buffer));
}
void Example(matlab::mex::ArgumentList outputs, const userStruct2& input)
{
StructArray out = factory.createStructArray({ 1 }, { "a", "b", "c", "d", "e" });
out[0]["a"] = VectorToArray(input.a);
out[0]["b"] = VectorToArray(input.b);
out[0]["c"] = factory.createScalar(input.c);
out[0]["d"] = factory.createScalar(input.d);
out[0]["e"] = CppCharToMatlab(input.e, std::extent_v<decltype(input.e)>);
outputs[0] = std::move(out);
}
  댓글 수: 1
Walter Roberson
Walter Roberson 2024년 10월 25일 18:59
your code is risky because MATLAB chars are UTF16 encoded while C++ chars are usually UTF8 encoded.
The discussion is further complicated because Simulink does not support char signals, but does support what it calls string signals. string signals are explicitly said to be ISO/IEC 8859-1 (that is, 8 bit with no surrogate code points.)

댓글을 달려면 로그인하십시오.

추가 답변 (1개)

Friedrich
Friedrich 2024년 10월 24일 11:41
Nevermind, I found the solution right after I posted my question. For those who have the same problem, here is an example
using namespace matlab::data;
class MexFunction : public matlab::mex::Function {
public:
void operator()(matlab::mex::ArgumentList outputs, matlab::mex::ArgumentList inputs) {
ArrayFactory factory;
StructArray out = factory.createStructArray({ 1 }, { "a", "b", "c", "d", "e"});
out[0]["a"] = factory.createArray<double>({ 3, 1 }, { 1, 2, 3 });
out[0]["b"] = factory.createArray<double>({ 5, 1 }, { 1, 2, 3, 4, 5 });
out[0]["c"] = factory.createArray<double>({ 1, 1 }, { 0 });
out[0]["d"] = factory.createArray<bool>({ 1, 1 }, { true });
out[0]["e"] = factory.createCharArray("0123456789");
outputs[0] = std::move(out);
}
}
The only thing I don't know yet is how to easily pass long arrays into the fields of "a" or "b".

태그

제품


릴리스

R2021b

Community Treasure Hunt

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

Start Hunting!

Translated by