如何构建一个指向matlab::data::Array对象的Eigen::Map,并打算用数据填充它

hk8txs48  于 2023-06-06  发布在  Matlab
关注(0)|答案(1)|浏览(185)

这个问题是上一个关于在Matlab Data API for C++中构建输入matlab::data::Array对象的Eigen::Map问题的后续问题。现在我想知道如何实现类似的东西,但是要实现一个输出数组,在循环遍历它时用数据填充它。
在上一个问题中,我从Matlab's forums实现了链接解决方案。在这里,我尝试使用以下方法来获取一个非常量指针:

template <typename T>
T* getOutDataPtr(matlab::data::Array arr) {
  matlab::data::TypedArray<T> arr_t = arr;
  matlab::data::TypedIterator<T> it(arr_t.begin());
  return it.operator->();
}

它的用法是这样的:

// Initialize input parameters
long int numEl = inputs[0][0];
long int na = inputs[0][1];
long int nPoints = inputs[0][2];
        
// Preallocate output and define map to output array
outputs[0] = factory.createArray<double>
  ({static_cast<size_t>(nPoints),static_cast<size_t>(numEl*na)});
        
auto ptrRecon = getOutDataPtr<double>(outputs[0]);
Eigen::Map<Eigen::MatrixXd> Recon(ptrRecon,nPoints,numEl*na);

for(int i = 0; i < nPoints; i++) {
 for(int n = 0; n < na; n++) {
  for (int j = 0; j < numEl; j++) {
   Recon(i,n*numEl + j) = 5.0;
  }
 }    
}

然而,即使是这样一个简单的赋值,我也会在编译和Matlab崩溃后遇到运行时错误。到底出了什么问题?

其他试验我还尝试了以下的内部循环,似乎确实有效:

for(int i = 0; i < nPoints; i++) {
    for(int n = 0; n < na; n++) {
        for (int j = 0; j < numEl; j++) {
            outputs[0][i][n*numEl + j] = 5.0;

        }
    }    
}

我怀疑这意味着我获取输出matlab数据数组指针的方式有问题?

e0bqpujr

e0bqpujr1#

这只是一个猜测,因为我将离开相当平庸的Matlab API文档,并且没有Matlab许可证来测试它。所以请你对这件事持保留态度。
我看到的一个区别是,您创建了一个可变迭代器TypedIterator<T>,而不是Matlab论坛中使用的TypedIterator<const T>。你可以在一个函数中实现这一点,该函数接受matlab::data::Array的值。这将创建共享数据副本。据我所知,这些是写时复制。
我的假设是,无论是构造迭代器还是以一种可以修改共享数组的方式使用迭代器,都会“取消共享”它,从而有效地创建一个副本。但是,该副本将被限制在参数的生命周期内,即函数。函数返回后,它就变成了一个悬空指针。
尝试将函数签名更改为T* getOutDataPtr(matlab::data::Array& arr)。或者将代码内联到主函数中。

编辑

实际上,这种改变是不够的,因为您要从Array构造TypedArray<T>。这也算作共享副本。尝试使用getWritableElements

template <typename T>
T* getOutDataPtr(matlab::data::Array& arr) {
  auto range = matlab::data::getWritableElements<T>(arr);
  return range.begin().operator->();
}

相关问题