如何将 matlab::data::TypedArray<double> 作为指针传递到 MATLAB mex 文件中构造犰狳矩阵?
How to pass matlab::data::TypedArray<double> as pointer to construct Armadillo matrix in MATLAB mex file?
有经验的人可以告诉我如何实现上述目标吗?
这肯定是小事;然而,经过许多日日夜夜的尝试、研究和上网阅读,我仍然无法理解它。
设置:
两个 C++ 源文件和一个头文件:
main.cpp
- 包含MATLAB和C++之间的通用IO接口
- 将两个 double 数组(每个数组的维度:ncols:168,nrows:2)和两个 double const double 输入 C++
- 它通过调用 foo()
做一些基于犰狳的循环(这部分不那么重要因此省略)
- returns outp 这是一个“普通”标量 double
- 没什么花哨或复杂的。
sub.cpp
- 这仅适用于 foo() 循环部分。
- 问题是两个 arma::mat mY 和 arma::mat mD 矩阵无法正确填充指向辅助内存的指针,如以下犰狳文档所述。
- http://arma.sourceforge.net/docs.html#adv_constructors_mat
sub.hpp
- 只是一个简单的头文件。
如有任何帮助、提示或建设性意见,我将不胜感激。
// main.cpp
// MATLAB API Header Files
#include "mex.hpp"
#include "mexAdapter.hpp"
// Custom header
#include "sub.hpp"
// Overloading the function call operator, thus class acts as a functor
class MexFunction : public matlab::mex::Function {
public:
void operator()(matlab::mex::ArgumentList outputs,
matlab::mex::ArgumentList inputs){
matlab::data::ArrayFactory factory;
// Validate arguments
checkArguments(outputs, inputs);
double* darrY = matlab::data::TypedArray<double>(std::move(inputs[0])).release().get();
double* darrD = matlab::data::TypedArray<double>(std::move(inputs[1])).release().get();
const double csT = inputs[2][0];
const double csKy = inputs[3][0];
// data type of outp is "just" a plain double, NOT a double array
double outp = foo(darrY, darrD, csT, csKy);
outputs[0] = factory.createScalar(outp);
void checkArguments(matlab::mex::ArgumentList outputs, matlab::mex::ArgumentList inputs){
// Create pointer to MATLAB engine
std::shared_ptr<matlab::engine::MATLABEngine> matlabPtr = getEngine();
// Create array factory, allows us to create MATLAB arrays in C++
matlab::data::ArrayFactory factory;
// Check input size and types
if (inputs[0].getType() != ArrayType::DOUBLE ||
inputs[0].getType() == ArrayType::COMPLEX_DOUBLE)
{
// Throw error directly into MATLAB if type does not match
matlabPtr->feval(u"error", 0,
std::vector<Array>({ factory.createScalar("Input must be double array.") }));
}
// Check output size
if (outputs.size() > 1) {
matlabPtr->feval(u"error", 0,
std::vector<Array>({ factory.createScalar("Only one output is returned.") }));
}
}
};
// sub.cpp
#include "sub.hpp"
#include "armadillo"
double foo(double dY[], double dD[], const double T, const double Ky) {
double sum = 0;
// Conversion of inputs parameters to armadillo matrices using the armadillo's so called advanced matrix constructor:
// mat(ptr_aux_mem, n_rows, n_cols, copy_aux_mem = true, strict = false)
// Fixme: parameterize n_rows, n_colss
arma::mat mY(&dY[0], 2, 168, false);
arma::mat mD(&dD[0], 2, 168, false);
// Armadillo calculations
for(int t=0; t<int(T); t++){
// some armadillo based calculation
// each for cycle increments sum by its return value
}
return sum;
}
// sub.hpp
#ifndef SUB_H_INCLUDED
#define SUB_H_INCLUDED
double foo(double dY[], double dD[], const double T, const double Ky);
#endif // SUB_H_INCLUDED
MATLAB Central 也有类似的问题。换行
double* darrY = matlab::data::TypedArray<double>(std::move(inputs[0])).release().get();
double* darrD = matlab::data::TypedArray<double>(std::move(inputs[1])).release().get();
至
TypedArray<double> matrix1 = std::move(inputs[0]);
TypedArray<double> matrix2 = std::move(inputs[1]);
buffer_ptr_t<double> Y = matrix1.release();
buffer_ptr_t<double> D = matrix2.release();
double* darrY = Y.get();
double* darrD = D.get();
似乎解决了问题。当我调试您的代码时,由于某种原因,两个矩阵似乎都获得了相同的地址。
有经验的人可以告诉我如何实现上述目标吗?
这肯定是小事;然而,经过许多日日夜夜的尝试、研究和上网阅读,我仍然无法理解它。
设置:
两个 C++ 源文件和一个头文件:
main.cpp
- 包含MATLAB和C++之间的通用IO接口
- 将两个 double 数组(每个数组的维度:ncols:168,nrows:2)和两个 double const double 输入 C++
- 它通过调用 foo() 做一些基于犰狳的循环(这部分不那么重要因此省略)
- returns outp 这是一个“普通”标量 double
- 没什么花哨或复杂的。
sub.cpp
- 这仅适用于 foo() 循环部分。
- 问题是两个 arma::mat mY 和 arma::mat mD 矩阵无法正确填充指向辅助内存的指针,如以下犰狳文档所述。
- http://arma.sourceforge.net/docs.html#adv_constructors_mat
sub.hpp
- 只是一个简单的头文件。
如有任何帮助、提示或建设性意见,我将不胜感激。
// main.cpp
// MATLAB API Header Files
#include "mex.hpp"
#include "mexAdapter.hpp"
// Custom header
#include "sub.hpp"
// Overloading the function call operator, thus class acts as a functor
class MexFunction : public matlab::mex::Function {
public:
void operator()(matlab::mex::ArgumentList outputs,
matlab::mex::ArgumentList inputs){
matlab::data::ArrayFactory factory;
// Validate arguments
checkArguments(outputs, inputs);
double* darrY = matlab::data::TypedArray<double>(std::move(inputs[0])).release().get();
double* darrD = matlab::data::TypedArray<double>(std::move(inputs[1])).release().get();
const double csT = inputs[2][0];
const double csKy = inputs[3][0];
// data type of outp is "just" a plain double, NOT a double array
double outp = foo(darrY, darrD, csT, csKy);
outputs[0] = factory.createScalar(outp);
void checkArguments(matlab::mex::ArgumentList outputs, matlab::mex::ArgumentList inputs){
// Create pointer to MATLAB engine
std::shared_ptr<matlab::engine::MATLABEngine> matlabPtr = getEngine();
// Create array factory, allows us to create MATLAB arrays in C++
matlab::data::ArrayFactory factory;
// Check input size and types
if (inputs[0].getType() != ArrayType::DOUBLE ||
inputs[0].getType() == ArrayType::COMPLEX_DOUBLE)
{
// Throw error directly into MATLAB if type does not match
matlabPtr->feval(u"error", 0,
std::vector<Array>({ factory.createScalar("Input must be double array.") }));
}
// Check output size
if (outputs.size() > 1) {
matlabPtr->feval(u"error", 0,
std::vector<Array>({ factory.createScalar("Only one output is returned.") }));
}
}
};
// sub.cpp
#include "sub.hpp"
#include "armadillo"
double foo(double dY[], double dD[], const double T, const double Ky) {
double sum = 0;
// Conversion of inputs parameters to armadillo matrices using the armadillo's so called advanced matrix constructor:
// mat(ptr_aux_mem, n_rows, n_cols, copy_aux_mem = true, strict = false)
// Fixme: parameterize n_rows, n_colss
arma::mat mY(&dY[0], 2, 168, false);
arma::mat mD(&dD[0], 2, 168, false);
// Armadillo calculations
for(int t=0; t<int(T); t++){
// some armadillo based calculation
// each for cycle increments sum by its return value
}
return sum;
}
// sub.hpp
#ifndef SUB_H_INCLUDED
#define SUB_H_INCLUDED
double foo(double dY[], double dD[], const double T, const double Ky);
#endif // SUB_H_INCLUDED
MATLAB Central 也有类似的问题。换行
double* darrY = matlab::data::TypedArray<double>(std::move(inputs[0])).release().get();
double* darrD = matlab::data::TypedArray<double>(std::move(inputs[1])).release().get();
至
TypedArray<double> matrix1 = std::move(inputs[0]);
TypedArray<double> matrix2 = std::move(inputs[1]);
buffer_ptr_t<double> Y = matrix1.release();
buffer_ptr_t<double> D = matrix2.release();
double* darrY = Y.get();
double* darrD = D.get();
似乎解决了问题。当我调试您的代码时,由于某种原因,两个矩阵似乎都获得了相同的地址。