在 C 中使用特征对象

Using eigen objects in C

我想在 C 中包装 Eigen 的部分功能,但我很好奇在这种情况下自动存储持续时间将如何工作。例如:

/* eigenwrapper.h */
#ifdef __cplusplus
extern "C" {
#endif


void* create_matrix(int r, int c);
//and other declarations like addition, multiplication, delete ... ....

#ifdef __cplusplus
}
#endif

`

/* eigenwrapper.cxx */
#include <eigen headers>
#include "eigenwrapper.h"

extern "C" {

void* create_matrix(int r, int c) {
    return &MatrixXf(r,c);

}

// and other definitions

}

`

/*main.c*/
#include "eigenwrapper.h"

int main(void) {
    m = create_matrix(3,3);
    /* working with m */
}

我假设 Eigen 或 C++ 会跟踪对象的引用数,但是当我 return 对象指针指向 C 函数时这会起作用吗?离开create_matrix函数时对象会被解构吗?

如果这样自动存储时长不起作用,我是否应该使用 new 关键字进行动态分配?例如return new MatrixXf(r,c); 那么当我有函数 returns matA * matB?

时,我如何获得动态分配的 newed 矩阵

正如其他人所指出的,C++ 不跟踪引用。如果你想要一个C API,你必须自己处理这个。

不透明指针

就将 Eigen 函数包装到 C API 而言,我会使用不透明指针而不是 void*,这样您至少有一些类型安全。

这里有一个合适的header:

#pragma once

#include <stddef.h>
/* using ptrdiff_t */

/** forward-declared opaque handle for matrix */
typedef struct EigenMatrixXf EigenMatrixXf;

#ifdef __cplusplus
extern "C" {
#endif

EigenMatrixXf* eigen_matrixxf_create(ptrdiff_t rows, ptrdiff_t cols);
EigenMatrixXf* eigen_matrixxf_add(
      const EigenMatrixXf* left, const EigenMatrixXf* right);
void eigen_matrixxf_free(EigenMatrixXf* self);

#ifdef __cplusplus
} /* extern "C" */
#endif

这里是 cpp 文件


struct EigenMatrixXf
{
    Eigen::MatrixXf mat;
};
EigenMatrixXf* eigen_matrixxcf_create(ptrdiff_t rows, ptrdiff_t cols)
try {
    return new EigenMatrixXf{ Eigen::MatrixXf(rows, cols) };
} catch(std::bad_alloc&) {
    errno = ENOMEM;
    return nullptr;
}
EigenMatrixXf* eigen_matrixxf_add(
      const EigenMatrixXf* left, const EigenMatrixXf* right)
try {
    return new EigenMatrixXf{ left->mat + right->mat };
} catch(std::bad_alloc&) {
    errno = ENOMEM;
    return nullptr;
}
void eigen_matrixxcf_free(EigenMatrixXf* self)
{ delete self; }

如果您想使用 fixed-size Eigen objects,请阅读此处的分配器问题:https://eigen.tuxfamily.org/dox/group__TopicStructHavingEigenMembers.html

映射 C 结构

您还可以使用 Eigen 的 Map 函数为 C 结构提供 Eigen viewhttps://eigen.tuxfamily.org/dox/group__TutorialMapClass.html 在 API 设计和性能(例如动态分配的数量、对齐方式等)方面,这里有一些权衡取舍

Header:

#pragma once

#include <stddef.h>
/* using ptrdiff_t */

typedef struct EigenMatrixXf
{
    float* ptr;
    ptrdiff_t rows, cols;
} EigenMatrixXf;

#ifdef __cplusplus
extern "C" {
#endif

EigenMatrixXf eigen_matrixxf_create(ptrdiff_t rows, ptrdiff_t cols);
EigenMatrixXf eigen_matrixxf_add(
    const EigenMatrixXf* left, const EigenMatrixXf* right);
void eigen_matrixxf_free(EigenMatrixXf* self);

#ifdef __cplusplus
} /* extern "C" */
#endif

Cpp 文件:


inline Eigen::MatrixXf::MapType map(EigenMatrixXf& ctype)
{ return Eigen::MatrixXf::MapType(ctype.ptr, ctype.rows, ctype.cols); };

inline Eigen::MatrixXf::ConstMapType map(const EigenMatrixXf& ctype)
{ return Eigen::MatrixXf::ConstMapType(ctype.ptr, ctype.rows, ctype.cols); };

EigenMatrixXf eigen_matrixxf_create(ptrdiff_t rows, ptrdiff_t cols)
try {
    return EigenMatrixXf { new float[rows * cols], rows, cols };
} catch(std::bad_alloc&) {
    errno = ENOMEM;
    return EigenMatrixXf { nullptr, 0, 0 };
}
EigenMatrixXf eigen_matrixxf_add(
      const EigenMatrixXf* left, const EigenMatrixXf* right)
{
    EigenMatrixXf rtrn = eigen_matrixxf_create(left->rows, left->cols);
    if(! rtrn.ptr)
      return rtrn;
    map(rtrn) = map(*left) + map(*right);
    return rtrn;
}
void eigen_matrixxf_free(EigenMatrixXf* self)
{ delete[] self->ptr; }