【问题标题】:Passing a vector to a function and return the vector and recast将向量传递给函数并返回向量并重铸
【发布时间】:2012-08-08 22:52:56
【问题描述】:

我正在使用 MEX 将我的 C++ 代码与 MATLAB 接口。我的 C++ 代码要求输出类型为 vector 。由于我是 C++ 新手,我对指针的工作方式非常困惑。我将从 MATLAB 中获取一个输入数组

int *data_array_ptr
data_array_ptr=(int *)mxGetData(prhs[0]);
a = mxGetM(prhs[0]);
int int_data[a];
copy(*data_array_ptr, *data_array_ptr+ a, int_data);

现在,int_data 应该拥有存储在 data_array_ptr 位置的所有数据...它这样做了吗?

那么,

double *data_out_ptr;

plhs[0]= mxCreateDoubleMatrix( (mwSize)m, (mwSize)n, mxREAL); 
data_out_ptr= mxGetPr(plhs[0]);
len6=mxGetM(plhs[0]);
vector<double> data_out_data(*data_out_ptr,*data_out_ptr+len6);

这应该将空输出矩阵的内容放入名为 data_out_data 的向量中。它会这样做吗?

然后,我想将 data_out_data 和 int_data 都传递给 c++ 函数。但是,我想将 data_out_data 作为指针传递,以便 c++ 函数将用数据填充向量,然后当函数完成时,MEX 函数将看到现在填充的向量并能够将其转换回双精度数组可以填充plhs[0]。

所以,像

mexFunction(plhs[],prhs[]){

int *data_array_ptr
data_array_ptr=(int *)mxGetData(prhs[0]);
a = mxGetM(prhs[0]);
int int_data[a];
copy(*data_array_ptr, *data_array_ptr+ a, int_data);

 double *data_out_ptr;
plhs[0]= mxCreateDoubleMatrix( (mwSize)m, (mwSize)n, mxREAL); 
data_out_ptr= mxGetPr(plhs[0]);
len6=mxGetM(plhs[0]);
vector<double> data_out_data(*data_out_ptr,*data_out_ptr+len6);



foo(int_data, *data_out_data)

copy(data_out_data.begin(), data_out_data.end(), data_out_ptr);
}

在 foo 返回时,data_out_data 将被填充。我的函数没有返回参数 data_out_data 必须是向量类型。如何将向量传递给 foo 以便 foo 可以编辑数据?

谢谢!!

【问题讨论】:

  • 不要取消引用copy 中的指针或vector 的构造函数参数。
  • @Aesthete a 设置为输入数组的大小,m 和 n 是输出数组的大小,例如 m=1 和 n=4

标签: c++ matlab pointers vector mex


【解决方案1】:

我不确定我是否正确理解了您的问题。我相信您想将一个数组从 MATLAB 传递给您的 mex 函数,然后 mex 函数调用一个对该数据数组进行操作的 C++ 函数,以及一个 vectorvector 然后包含 C++ 函数执行的任何操作的结果,并且您希望将此数据传递回 MATLAB。


首先,让我们处理将数据从 MATLAB 获取到您的 MEX 函数

int const *data_in = static_cast<int const *>(mxGetData(prhs[0]));

现在,data_in 指向您传入的数据。顺便问一下,您确定数组包含ints 吗?默认情况下,MATLAB 对所有内容都使用double

你的 C++ 函数会修改这个数组吗?如果没有,您可以只使用指针和元素数调用它,而不是执行复制。

例如,如果foo的签名是

foo( int const *data_in, mwSize num_data_in, std::vector<double> *data_out );

你可以这样称呼它

foo( data_in, mxGetNumberOfElements(prhs[0]), &data_out );

如果您确实需要修改数据,并且/或者无法修改foo,只需创建一个向量来保存数据的副本。

std::vector<int> data_in_vec( data_in, data_in + mxGetNumberOfElements(prhs[0]) );
foo( data_in_vec.data(), data_out );

对于foo 函数,在调用它之前是否需要正确调整向量的大小?如果是这样,

std::vector<double> data_out( m * n );  // creates a vector with m * n elements
foo( data_in_vec.data(), &data_out );

如果可能,修改foo 以接受std::vector&lt;double&gt;&amp; 而不是std::vector&lt;double&gt; *。然后你可以把它称为

foo( data_in_vec.data(), data_out );

另外,如果可以选择,我会让foo 根据需要调整向量的大小,而不是要求调用者这样做。


现在,将数据返回到 MATLAB。

plhs[0] = mxCreateDoubleMatrix( m, n, mxReal );
std::copy( data_out.data(), data_out.data() + data_out.size(), mxGetPr(plhs[0]) );

以上行假设向量的大小不大于m * n

请记住,MATLAB 以列优先格式存储矩阵,这与 C 和 C++ 不同。根据foo 函数的工作方式,您可能需要转置返回的向量,在这种情况下您不能使用std::copy 进行复制,您必须编写嵌套循环。

【讨论】:

  • 从 Matlab 中,数组的大小已经正确,所以这不是问题,我在 foo 内部调用了其他类,它们将填充 data_out 向量中的数据。这些类已经写好并且只接受向量,我希望可能将一个指针传递给 foo 用于向量 data_out,然后用空向量调用类,然后在类填充 data_out 之后,指针现在可以看到新数据和因此,我的 MEX 函数也是如此。
  • @user1586097 您不能将向量传回 MATLAB 或使向量和由mxCreateDoubleMatrix 创建的矩阵共享同一个数据缓冲区。在foo 完成对向量的操作后,您必须将向量的内容复制回plhs[0] 的矩阵中。
  • 如果我像你说的那样调用 foo:如果可能,修改 foo 以接受 std::vector& 而不是 std::vector *。那么你可以将它称为 foo( data_in_vec.data(), data_out ) 如果我将data_out 传递给另一个类,它是数据向量的第一个元素的地址还是实际数据?我的课需要一个实际的向量。但我也希望在 MEX 中返回 foo 时看到类编辑的向量。
  • @user1586097 Here's an answer 解释指针和引用之间的区别。引用指的是原始变量,因此您可以使用它来做任何您可以使用原始变量的事情。此外,如果您对引用进行修改,它也会修改原始变量(因为它们都是相同的)
  • 谢谢。现在我的问题是copy(data_array_ptr, data_array_ptr+ a, int_data) 这行应该获取 data_array_ptr 指向的整个数组,并将其重新转换为 int_data 是什么,在这种情况下是一个整数数组。因此 int_data 将具有来自 data_array_ptr 的数据,但转换为 int 类型。但是,编译器告诉我 int_data 的类型为 int*
【解决方案2】:

您对指针的解引用超出了应有的范围...

int *data_array_ptr;
// ...
copy(*data_array_ptr, *data_array_ptr+ a, int_data);

当您被要求提供指向 copy 的开始和结束指针时,您需要这样做:

copy(data_array_ptr, data_array_ptr+ a, int_data);

现在您已经提供了两个内存地址。第一个 data_array_ptr 是数组的起始地址。第二个,data_array_ptr+a 是数组末尾之后元素的地址。

如果您取消引用指针 (*data_array_ptr),那么您要求的是数组第一个元素的 int)。同样,*data_array_ptr+a 将首先获取第一个数组元素的值,然后将a 添加到它。这不是你想要的。

因此,按照建议将您的所有调用更改为 copy,以及您的 vector 构造函数。

至于您对foo 函数的问题,如果您需要传递一个向量,请像这样声明它:

void foo( int * int_data, std::vector<double> & data_out_data )

假设您在上面提供了这些变量的定义。我认为你是这样称呼的:

// ...

int int_data[a];
copy(*data_array_ptr, *data_array_ptr+ a, int_data);

// ...

vector<double> data_out_data(data_out_ptr, data_out_ptr+len6);

// ...

foo( int_data, data_out_data );

请注意,如果您不知道foo 内的int_data 数组的长度(基于data_out_data 的长度),您还应该在foo 的参数列表中要求一个大小:

foo( int_data, a, data_out_data );

【讨论】:

  • 这非常有帮助,谢谢!如果我需要使用指向向量的指针调用 foo,以便在 foo 内部,可以取消引用指针,然后将使用取消引用的数据调用类,然后类将返回新数据,然后指针将指向新的MEX 函数在 foo 返回时查看的数据。
  • 那很好。我指定了对向量的引用而不是指针。如果您愿意,可以使用指针,但在传递 STL 容器时引用更常见。您仍然可以在foo 中获取引用对象的地址来获取指针(ie &amp;data_out_data)。这里的重点是您正在向 foo 传递对向量的本地副本的引用。因此,在调用foo 期间对向量所做的任何更改都将在foo 返回时出现。
  • 如果我像foo(int_data, &amp;data_out_data) 一样调用foo 并且foo 被定义为foo(int int_data[], vector&lt;double&gt; *data_out_data) 那么data_out_data 的第一个元素的地址将被取消引用到foo 中?还是我还需要做一些事情来将该向量引用传递给另一个类?还是应该将 foo 定义为 &data_out_data 而不是 *data_out_data? @paddy
  • @user1586097 不,data_out_data 是双精度向量。因此,您没有传递指向第一个元素的指针 - 您正在传递指向向量的指针(vector&lt;double&gt; 类的实例)。如果您想将向量作为指针传递,您在那里给出的函数调用和声明很好。引用几乎与指针相同,除了在语法上您使用它时就好像它不是指针一样。所以要附加到一个向量指针,你会使用v-&gt;push_back(),但如果它是一个向量引用,你会使用v.push_back()。您不必显式引用或取消引用引用!
  • 好的,所以如果我通过引用传递一个向量,我是否需要在 foo 中创建一个新的向量副本以允许我发送该向量以在另一个类中进行处理?然后在 v.pushback 类的返回上设置对现在填充的复制向量的引用?
猜你喜欢
  • 2017-06-27
  • 1970-01-01
  • 2021-12-10
  • 1970-01-01
  • 2015-08-07
  • 2013-06-04
  • 1970-01-01
  • 2016-11-09
  • 2011-12-02
相关资源
最近更新 更多