【发布时间】:2022-01-05 07:18:01
【问题描述】:
我想将 Eigen 的部分功能封装在 C 中,但我很好奇在这种情况下自动存储持续时间将如何工作。例如:
/* 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++ 会跟踪对象的引用数量,但是当我将对象的指针返回给 C 函数时,这会起作用吗?离开create_matrix函数时对象会被解构吗?
如果自动存储时长不能这样工作,我应该使用new 关键字进行动态分配吗?例如return new MatrixXf(r,c); 那么当我有一个函数返回matA * matB 时,我怎样才能获得动态分配的newed 矩阵呢?
【问题讨论】:
-
如果你想在 C 中管理自动存储,你必须明确标记什么时候进入和超出范围。一个突出的例子是 Python C API。如果您正在编写适用于 Python 数据类型的 C 代码,您必须在变量“进入范围”时调用
Py_INCREF,在变量“退出范围”时调用Py_DECREF。这是你的工作,因为 C 不会为你做这件事。 -
&MatrixXf(r,c)没有意义。使用new创建一个对象并获取指向它的指针。返回到 C 代码后,将指针用作 opaque pointer 并将其传递给所有需要它的 C++ 函数。然后,C++ 函数必须执行reinterpret_cast<MatrixXf*>(ptr)才能获得指向该对象的正确指针。您还需要一个显式的 API 函数来删除该对象。 -
另一方面,在 C++ 中,所有指向对象的指针都可以隐式转换为
void*,您不需要为此进行强制转换。在这一点上,每当你觉得需要在 C++ 中进行 C 风格的转换时,你应该把它当作你可能做错了什么的迹象。 -
在 C 中包装矩阵 c++ 库没有意义。如果你真的需要纯 c,找一个带有 c API 的矩阵库,比如 LAPACK。但请考虑在 C++ 中进行矩阵计算。
-
“我假设 Eigen 或 C++ 会跟踪对象的引用数量”——不,这不会发生,除非你使用像
std::shared_ptr这样的东西。我认为,获取右值的地址也是不合法的(我不是语言律师......)