C++ :: 如何捕获由 void 函数创建的矩阵
C++ :: how to capture matrix created by void function
我通常用python编码,但由于组合爆炸,我决定使用C++来解决一个问题。我的想法是将 numpy 数组保存在 npy 文件中,然后我将向我的 C++ 函数提供该 npy 文件。由于我对C++指针和引用的理解有限,因此我无法围绕如何获取 void 函数的值来思考。void 函数不返回任何内容,所以我不能使用通常的赋值操作。如何将新的(&mat_out(分配给我想要的变量,比如A。或者通过返回值(如第二个注释函数(来做到这一点的另一种方法,但在这种方法中,我遇到了类型不匹配。我的主要问题是如何使其中任何一个方法起作用。但从知识的角度来看,我还想知道如何使用在 void 函数中创建的新对象。
#include <iostream>
#include <Eigen/Dense>
#include "cnpy.h"
#include "opencv2/highgui.hpp"
using namespace std;
using namespace Eigen;
using namespace cv;
void cnpy2eigen(string data_fname, Eigen::MatrixXd& mat_out){
cnpy::NpyArray npy_data = cnpy::npy_load(data_fname);
// double* ptr = npy_data.data<double>();
int data_row = npy_data.shape[0];
int data_col = npy_data.shape[1];
double* ptr = static_cast<double *>(malloc(data_row * data_col * sizeof(double)));
memcpy(ptr, npy_data.data<double>(), data_row * data_col * sizeof(double));
cv::Mat dmat = cv::Mat(cv::Size(data_col, data_row), CV_64F, ptr); // CV_64F is equivalent double
new (&mat_out) Eigen::Map<Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic>>(reinterpret_cast<double *>(dmat.data), data_col, data_row);
}
/*
Eigen::Map<Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> > * cnpy2eigen(string data_fname){
cnpy::NpyArray npy_data = cnpy::npy_load(data_fname);
// double* ptr = npy_data.data<double>();
int data_row = npy_data.shape[0];
int data_col = npy_data.shape[1];
double* ptr = static_cast<double *>(malloc(data_row * data_col * sizeof(double)));
memcpy(ptr, npy_data.data<double>(), data_row * data_col * sizeof(double));
cv::Mat dmat = cv::Mat(cv::Size(data_col, data_row), CV_64F, ptr); // CV_64F is equivalent double
return new (&mat_out) Eigen::Map<Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic>>(reinterpret_cast<double *>(dmat.data), data_col, data_row);
}
*/
int main()
{
Eigen::MatrixXd& A = cnpy2eigen("/Users/osmanmamun/Play_Ground/C++_practice/bayesframe/X_data.npy", Eigen::MatrixXd& A);
cout << "Here is the matrix A:n" << A << endl;
}
免责声明:我从博客中获得了 cnpy2eigen 函数。
你发布的代码有很多问题
#include <iostream>
#include <Eigen/Dense> // minor remark: Often you just need <Eigen/Core> here
#include "cnpy.h"
#include "opencv2/highgui.hpp" // Do you actually need OpenCV here?
using namespace std;
using namespace Eigen;
using namespace cv;
(几乎(永远不要把using namespace X;
放在全球范围内![1]
void cnpy2eigen(string data_fname, Eigen::MatrixXd& mat_out){ // minor remark: Better pass `std::string` by const reference
cnpy::NpyArray npy_data = cnpy::npy_load(data_fname);
// double* ptr = npy_data.data<double>();
int data_row = npy_data.shape[0];
int data_col = npy_data.shape[1];
double* ptr = static_cast<double *>(malloc(data_row * data_col * sizeof(double)));
您在此处malloc
数据,但没有匹配的free
。首先,标准的"低级"C++将使用new
和delete
(不过std::vector
使用更好(。但实际上你可以改用 Eigen 的内存分配。
memcpy(ptr, npy_data.data<double>(), data_row * data_col * sizeof(double));
例如,标准C++将使用std::copy
(不过,这也将在内部转换为 POD 类型的memcpy
(。但实际上没有必要在这里手动复制。
cv::Mat dmat = cv::Mat(cv::Size(data_col, data_row), CV_64F, ptr); // CV_64F is equivalent double
您是否在任何地方使用dmat
?如果没有,请将其删除。另请注意,OpenCV 使用行主存储(我假设 numpy 使用列主存储?
new (&mat_out) Eigen::Map<Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic>>(reinterpret_cast<double *>(dmat.data), data_col, data_row);
在这里,您正在Eigen::Matrix
的内存位置上放置新的Eigen::Map
。这可能部分有效,因为这两种类型都意外地共享了它们的一些内存布局(但Eigen::Map
具有额外的成员变量(。此外,Eigen::Matrix
拥有它的内存,而Eigen::Map
没有,即当Eigen::Matrix
被破坏时,它将释放它不拥有的内存。通常,除非您知道自己在做什么,否则请避免使用新展示位置,尤其是对于不匹配的类型。(实际上,您几乎不需要在用户代码中new
(
}
这是一个修复/清理的版本:
void cnpy2eigen(std::string const& data_fname, Eigen::MatrixXd& mat_out){
cnpy::NpyArray npy_data = cnpy::npy_load(data_fname);
double* ptr = npy_data.data<double>();
int data_row = npy_data.shape[0];
int data_col = npy_data.shape[1];
mat_out = Eigen::MatrixXd::Map(ptr, data_row, data_col); // assuming NumPy is column major
}
这样称呼它:
int main()
{
Eigen::MatrixXd A;
cnpy2eigen("filename", A);
std::cout << "Here is the matrix A:n" << A << 'n';
}
如果您更喜欢按值返回,这应该有效:
Eigen::MatrixXd cnpy2eigen(std::string const& data_fname){
cnpy::NpyArray npy_data = cnpy::npy_load(data_fname);
double* ptr = npy_data.data<double>();
int data_row = npy_data.shape[0];
int data_col = npy_data.shape[1];
return Eigen::MatrixXd::Map(ptr, data_row, data_col); // assuming NumPy is column major
}
这样称呼它:
int main()
{
Eigen::MatrixXd A = cnpy2eigen("filename");
std::cout << "Here is the matrix A:n" << A << 'n';
}
如果你想避免复制,你需要保持npy_data
对象处于活动状态并直接使用Eigen::Map
(我认为没有办法将所有权从 cnpy 转移到 Eigen(。
- 如何创建函数管道,以便函数一个接一个地运行?
- 如何创建一个对象创建函数,该函数将由与其关联的名称调用?
- 创建函数变体向量时"No matching function for call"错误
- C++ 在映射中创建函数指针向量
- 以编程方式在 C++ 中创建函数
- 如何创建函数可能使用自定义可比C++?
- 编译错误,未创建函数/方法! 对于 brms 模型
- Cython 创建 C 函数别名
- 创建函数指针数组
- 动态创建函数并获取指针
- 混合模板类型的模板参数包(std::使用可选参数重新创建函数)
- 如何创建函数原型命名空间
- 无法创建函数数组
- 在为STD模板函数创建函数对象时,还要还原样板
- 是否可以在C++中声明基类,以便只能通过创建函数创建从它派生的类
- 将原始指针移动到已创建函数中的下一个字符
- qjsonObject如何创建函数
- 尝试在别人的代码中C++创建函数(A* 搜索)
- 在C++中通过模板包重新创建函数签名和调用
- 创建函数时接收"expected unqualified-id"