C++ API 声明在 Cython 中失败

4 投票
1 回答
985 浏览
提问于 2025-04-17 22:37

我有两个文件 module.pyxfoo.cpp。我想在 foo.cpp 中调用一个在 Cython 模块 module.pyx 中声明的函数。这个函数会返回一个指向向量的指针:

module.pyx:

#distuils: language = c++

from libcpp.vector cimport vector
from cython.operator cimport dereference as deref

cdef api vector[int] *func():
    cdef vector[int] *v = new vector[int]()
    deref(v).push_back(3)
    return v


foo.cpp:

#include "module_api.h"
#include <vector>
#include <iostream>

using namespace std;

int main() {
    import_module();
    vector<int> *v = func();
    cout << "v[0] = " << v[0] << endl;
}


我用下面的命令编译了 module.pyx

cython module.pyx --cplus

然后用这个命令编译 foo.cpp

g++ foo.cpp -I/Users/richizy/anaconda/include/python2.7/

但是它没有正常工作。我收到一个很大的错误信息,内容是“命名空间 'std' 中的 vector 不是一个类型”,还有很多其他的错误。问题出在哪里呢?

我使用的是 Anaconda 的 Python 版本,刚刚进行了干净的默认安装。

版本信息:

g++ (MacPorts gcc47 4.7.3_3+universal) 4.7.3

Cython 版本 0.20.1

Python 2.7.6 :: Anaconda 1.9.1 (x86_64)

Mac OS X 10.8.4

1 个回答

4

要在C或C++应用程序中使用Python引擎,你需要确保在你的main()函数开始时调用Py_Initialize(),并在结束时调用Py_Finalize()。另外,你可能没有注意到的是,import_module()函数实际上会产生一个错误,但它是通过Python的错误机制来处理的。你可以通过在import_module()下面添加以下代码来让这个错误变得明显:

if (PyErr_Occurred())
{
    PyErr_Print();
    return -1;
}

如果你这样做,你会看到以下错误信息出现:

ImportError: No module named module

要使用Cython模块,你必须确保调用该模块的初始化函数,在这个例子中是initmodule()。不幸的是,这个函数的声明似乎没有出现在生成的头文件中,所以我们需要手动将它添加到main函数的上方:

PyMODINIT_FUNC initmodule(void);

再加上把vector的包含行放在最前面,以及在cout行做一个小修正,代码就变成了:

#include <vector>
#include <iostream>
#include "module_api.h"

using namespace std;

PyMODINIT_FUNC initmodule(void);

int main() {
    Py_Initialize();
    initmodule();
    import_module();
    if (PyErr_Occurred())
    {
        PyErr_Print();
        return -1;
    }
    vector<int> *v = func();
    cout << "v[0] = " << (*v)[0] << endl;
    Py_Finalize();
    return 0;
}

在我的系统上,这样做的输出是:

v[0] = 3

撰写回答