在 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
?
时,我如何获得动态分配的 new
ed 矩阵
正如其他人所指出的,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 view。 https://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; }
我想在 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
?
new
ed 矩阵
正如其他人所指出的,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 view。 https://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; }