C ++ ::如何捕获由void函数创建的矩阵

问题描述 投票:0回答:1

我通常使用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函数。

c++ eigen
1个回答
0
投票
#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 ++将使用newdelete(不过最好使用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)。

© www.soinside.com 2019 - 2024. All rights reserved.