在Python中公开C ++全局变量

时间:2013-01-08 22:53:28

标签: c++ python arrays python-3.x cython

我正在尝试使用Cython在我的Python代码中访问C ++全局变量。

假设我的C ++代码中有以下数组:

// Project.cpp
int myArr[2] = { 0, 1 };

因此,在Cython中定义指向 myArr 的指针:

cdef extern int * myArr_ptr

myArr_ptr 真的指向C ++数组吗?或者只是一个随机值?

1 个答案:

答案 0 :(得分:4)

好的,问题是:

Project.cpp有一个全局int *myArr;,它未在Project.h中列出,您希望在不导入Project.cpp的情况下从Cython访问它。

在评论中,您说:

  

我不能包含Project.cpp,因为此文件将尝试包含已包含的其他文件,并将尝试重新定义许多变量。

您描述它的方式,这里可能存在一个基本错误。你可能知道这些基本的东西,所以请不要侮辱我把它们搞砸了,但我只想彻底:

首先,如果你的头文件没有防止多重包含,请修复它,然后你不必担心“我不能包含Project.cpp因为这个文件会尝试包含其他已经包含的文件将尝试重新定义许多变量。“ (如果你没有头文件,并且你只是在所有地方使用显式extern语句执行.cpp文件中的所有内容,请不要这样做 - 这在C和C ++中是个坏主意,在你进入Cythonizing之前。)

其次,如果您的模块要与Project.cpp所属的.so / .dll / .dylib接口,则不应该针对该库的源构建,而是针对已安装的接口构建。另一方面,如果您的模块是直接包含C ++代码,那么 包含Project.cpp。如果你使用extern声明引用你不会链接的东西,你只会得到一个链接器错误 - 或者,如果你运气不好,一切都将构建但在运行时失败。

第三,如果它实际上不是全局的,则无法从Project.cpp外部访问 - 出于范围,生命周期或链接的原因,在单独的实现文件中没有其他类型的变量可用。

再一次,我假设你知道所有这些基本的东西,我只是误读了你的评论。 是一个真正的问题案例,你需要用一个设计糟糕的API包装一些需要你进入内部的东西,这有时候很棘手,你可能碰到了这样的事情,我还没弄清楚究竟是怎么做的。

有三种基本解决方案。

首先,显然,如果你可以构建一个合适的原生API,那么在Cython中包装该API是微不足道的。而且这在其他原因同时也很有用。有时,这将是太多的时间和精力 - 例如,如果本机库不是设计为外部驱动的,并且是大量的10年遗留维护,并且是你必须要包装的唯一原因它是当前的Cython项目,您可能不想清理它。或者,如果它是一个快速变化的库,您需要及时更新并且没有源代码控制,分叉并尝试保持同步可能是一场噩梦。等等。但如果你的情况没有这样的理由,这是正确的答案。如果只能cdef extern from "project.h",一切都很简单。

您可以通过在本机级别创建“填充API”来创建更简单的版本,创建单独的.h文件,其中包含适用于各种,函数和类型的extern,function和type声明需要从内部使用。然后,您可以cdef extern from "project_extras.h"

最后,您总是可以为任何事情编写显式的cdef extern语句,而不会告诉Cython它来自何处。 Cython会将其转换为生成代码中的相应本机外部函数,如果一切正确,它将起作用。这里有一些缺点 - the docs解释了你将放弃的cdef extern from的所有优点。简短的版本是,您的Cython声明必须与本机声明完全匹配;否则,不是在Cython阶段自动修复或引发一个好的错误,你将从C编译器得到一个不可思议的错误消息,指的是不可读的Cython生成的C代码而不是你的实际代码 - 或者更糟糕的是,代码编译但做错了。

对于简单int *int []值的情况,所有这些都很重要,因为这不需要任何解释;简单的cdef extern应该没问题。