我通常使用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::Map
的存储位置上重新放置Eigen::Matrix
。这可能部分起作用,因为这两种类型意外地共享了它们的某些内存布局(但是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)。