【问题标题】:Using cython cdef public variable in c++ : variable is never initialized在 C++ 中使用 cython cdef 公共变量:变量永远不会被初始化
【发布时间】:2017-04-21 12:20:11
【问题描述】:

我正在尝试将一些简单的 cython 翻译成 c++:

cdef public int G = 1

然后在我的 c++ 代码中使用它:

#include <Python.h>
#include "test.h" // The file generated by the cython command
#include <iostream>
int main(int argc, char **argv) {
    std::cout << "G : " << G << std::endl;
}

输出是:

G : 0

我查看了test.cpp cython 生成的文件,在第 897 行,我有

  G = 1;

那么为什么 main 中的 G 被评估为 0 呢?

以下是用于编译的命令:

cython.exe test.pyx -3 --cplus
g++ test.cpp test_main.cpp -IC:\Python36-32\include -LC:\Python36-32\libs -lpython36

【问题讨论】:

  • 你如何编译和链接你的程序?如给定的,它不会链接。
  • @spectras 已编辑。我使用this answer 获取链接方面的帮助。

标签: python c++ cython


【解决方案1】:

使用cython 时生成的是一个python 扩展模块。您不能将其直接链接到可执行文件中,因为它需要动态导入并链接到 libpython。在该过程中,您的扩展程序的初始化函数将运行,这将导致您的 G 设置为 1。

所以你应该:

  • 从您的 cython 构建一个 python 扩展(使用 -shared 并输出一个 DLL)。
  • 在您的主文件中加载 python 解释器。在你的程序中,你现在甚至没有初始化 python。
  • 使用PyImport_ImportModule("mymodule") 将其导入您的主目录。

未经测试,但您的主要内容应如下所示:

#include <Python.h>

int main(int argc, char * argv[])
{
    Py_Initialize();
    PyObject * test_module = PyImport_ImportModule("test");

    // do something with test_module

    Py_Finalize();
    return 0;
}

您可以使用PyObject_GetAttrString() 从python 中获取G,或者由于您将其声明为cdef,您可以使用操作系统的符号解析工具直接访问它,例如Windows 的GetProcAddress()

也许可以在加载时动态链接,但仍然使用 importmodule 让 python 完成它的初始化魔法,但我不知道如何做到这一点,甚至不知道它是否可能。 p>

【讨论】:

  • 感谢您的回答。感觉比我预期的要复杂得多......我对一个函数做了同样的事情,没有导入模块一切都很好,只调用Py_InitializePy_Finalize
  • Cython 文档specifies a couple of different way of doing import/initialization 您可能会发现它稍微简单一些。基本思想与这个答案非常相似。
  • @DavidW 简直完美。 G 在调用PyInit_test 后为1(因为我使用的是python3,您提供的文档中有python2 的示例)
  • @B.Barbieri> 太棒了!是的,现在您提到它,这就是 ImportModule 所做的:它在模块内查找 PyInit_modulename 并调用它。所以如果你自己做它应该替换 DLL + importmodule 就好了。
猜你喜欢
  • 2010-12-26
  • 2017-05-06
  • 1970-01-01
  • 2020-03-27
  • 2021-09-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-30
相关资源
最近更新 更多