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
-ing 数据,但没有匹配 free
。首先,标准 "low-level" 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
)
}
这是一个 fixed/cleaned 升级版本:
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';
}
如果您更喜欢按值 return,这应该可行:
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 to Eigen).
我通常在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
-ing 数据,但没有匹配 free
。首先,标准 "low-level" 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
)
}
这是一个 fixed/cleaned 升级版本:
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';
}
如果您更喜欢按值 return,这应该可行:
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 to Eigen).