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

Expose a C++ global variable in Python

本文关键字:一个 C++ 全局变量 Python      更新时间:2023-10-16

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

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

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

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

cdef extern int * myArr_ptr

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

好的,问题是:

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

在评论中,你说:

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

按照你的描述,这里可能有一个基本错误。你可能知道这些基本的事情,所以请不要因为我提起它们而受到侮辱,但我只想彻底一点:

首先,如果您的头文件没有防止多重包含的保护措施,请修复此问题,然后您就不必担心"我不能包含Project.cpp,因为此文件将尝试包含已包含的其他文件,并尝试重新定义许多变量。"(如果你没有头文件,而你只是在.cpp文件中做所有的事情,到处都有显式的extern语句,不要这样做——这在C和C++中是个坏主意,早在你开始Cythoning之前。(

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

第三,如果它实际上不是全局的,那么就不能从Project.cpp之外进行访问——由于作用域、生存期或链接的原因,在单独的实现文件中没有其他类型的变量可用。

再说一遍,我想你知道所有这些基本的事情,我只是误解了你的评论。一个真正的问题案例,你需要用一个设计糟糕的API来包装一些东西,这需要你深入内部,有时这可能很棘手,你可能确实遇到了这样的事情,我只是还没有弄清楚具体是怎么回事。

有三个基本的解决方案。

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

您可以通过在本机级别创建一个"shim API",为需要从内部使用的各种函数和类型创建单独的.h文件,其中包含适当的外部、函数和类型声明,来实现更简单的版本。然后,您可以只使用cdef extern from "project_extras.h"

最后,您总是可以为任何内容编写显式的cdef extern语句,而无需告诉Cython其中任何语句的来源。Cython将在生成的代码中把它转换为适当的本地外部,如果你把一切都做好了,它就会工作。这里有一些缺点——文档解释了您将要放弃的cdef extern from的所有优点。简短的版本是,您的Cython声明必须与本机声明完全匹配;否则,您将不会在Cython阶段自动修复或引发一个漂亮的错误,而是从C编译器收到一条无法理解的错误消息,该消息指的是无法读取的Cython生成的C代码,而不是您的实际代码,或者更糟的是,指的是编译但做了错误事情的代码。

对于简单的int *int []值,所有这些都无关紧要,因为这不需要任何解释;一个普通的CCD_ 18应该很好。