C++/CLI 将托管 MathNet 矩阵转换为 Eigen MatrixXi 以在本机中使用 class

C++/CLI converting managed MathNet Matrix to Eigen MatrixXi for use in native class

我正在尝试为包含 Eigen::MatrixXi 的本机 C++ class 构建托管包装器。假设本机 class 有一个成员 matrix 存储并通过其构造函数获取,以及稍后使用该成员的方法:

#include <Eigen/Dense>
#include <Eigen/Core>
#include <iostream>

using Eigen::MatrixXi;

class Foo
{
public:
    const MatrixXi matrix;

    Foo(const MatrixXi &matrix);
    void Bar();
};

Foo::Foo(const MatrixXi &matrix)
    : matrix(matrix) {}

void Foo::Bar()
{
    for (int y = 0; y < matrix.rows(); y++)
    {
        for (int x = 0; x < matrix.cols(); x++)
        {
            std::cout << matrix(y, x);
        }
        std::cout << std::endl;
    }
}

我做了以下包装:

using namespace MathNet::Numerics::LinearAlgebra;
using namespace MathNet::Numerics::LinearAlgebra::Single;

template<class T>
public ref class ManagedObject
{
protected:
    T* m_Instance;
public:
    ManagedObject(T* instance)
        : m_Instance(instance)
    {
    }
    virtual ~ManagedObject()
    {
        if (m_Instance != nullptr)
        {
            delete m_Instance;
        }
    }
    !ManagedObject()
    {
        if (m_Instance != nullptr)
        {
            delete m_Instance;
        }
    }
    T* GetInstance()
    {
        return m_Instance;
    }
};

public ref class ManagedFoo : public ManagedObject<Foo>
{
public:
    ManagedFoo(MathNet::Numerics::LinearAlgebra::Matrix<float>^ matrix);
    void Bar();
};

ManagedFoo::ManagedFoo(MathNet::Numerics::LinearAlgebra::Matrix<float>^ matrix)
    : ManagedObject(new Foo(mathnet_to_eigen(matrix))) {}

void ManagedFoo::Bar()
{
    m_Instance->Bar();
}

mathnet_to_eigen 方法会是什么样子?我尝试了以下方法:

#include <vector>
#include <Eigen/Dense>
#include <Eigen/Core>

using Eigen::MatrixXi;

static Eigen::MatrixXi mathnet_to_eigen(MathNet::Numerics::LinearAlgebra::Matrix<float>^ data)
{
    int length = data->RowCount * data->ColumnCount;
    std::vector<int> data_converted(length);

    for (size_t i = 0; i < data->RowCount; i++)
    {
        for (size_t j = 0; j < data->ColumnCount; j++)
        {
            data_converted[i * data->ColumnCount + j] = data[i, j];
        }
    }

    Eigen::MatrixXi mat = Eigen::Map<Eigen::Matrix<int, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>>(&data_converted[0], data->RowCount, data->ColumnCount);

    return mat;
}

这似乎可行,但我不确定内存管理和效率。我应该使用固定吗?那会是什么样子?我感觉我做的不正确,可能使用了指向被垃圾收集的内存的指针。

在这种情况下,我不关心如何完成 float 到 int 的转换(rounding/taking 整数部分)。

我发现这是最简洁的方法:

static Eigen::MatrixXf MathNetToEigen(MathNet::Numerics::LinearAlgebra::Matrix<float>^ data)
{
    auto mat = Eigen::MatrixXf(data->RowCount, data->ColumnCount);
    for (size_t i = 0; i < data->RowCount; i++)
        for (size_t j = 0; j < data->ColumnCount; j++)
            mat(i, j) = data[i, j];

    return mat;
}

并转换回来:

static MathNet::Numerics::LinearAlgebra::Matrix<float>^ EigenToMathNet(Eigen::MatrixXf& data)
{
    auto mat = MathNet::Numerics::LinearAlgebra::Matrix<float>::Build->Dense(data.rows(), data.cols());
    for (size_t i = 0; i < data.rows(); i++)
        for (size_t j = 0; j < data.cols(); j++)
            mat[i, j] = data(i, j);

    return mat;
}