C++ API声明在Cython中失败

4
我有两个文件,分别是module.pyxfoo.cpp。我想要在foo.cpp中调用在cython模块module.pyx中声明的函数。这个函数会返回一个指向vector的指针。 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/

但是程序无法正常运行,出现了大量错误信息,其中包括“vector in namespace 'std' does not name a type”。请问问题出在哪里?

我正在使用Anaconda Python发行版,并进行了最近的干净和默认安装。

版本信息如下:

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

Cython version 0.20.1

Python 2.7.6 :: Anaconda 1.9.1 (x86_64)

Mac OS X 10.8.4


将两行代码 #include "module_api.h"#include <vector> 交换位置可以解决我的 vector 问题,但是接着我遇到了段错误。然而,我无法让文档中的 delorean 示例正常工作,所以我肯定还有其他问题。 - hivert
再次问候您,Hivert。在Google上漫游后,我认为我的错误是由于忘记与Python库的链接(在我的情况下,它位于/Users/richizy/anaconda/lib/python2.7/config/libpython2.7.a)引起的。但是,仍然像您所说的那样出现了段错误。 - richizy
段错误可能是因为在访问向量之前没有进行解引用。在C++文件中使用(*v)[0]而不是v[0] - IanH
嗯,看起来它在导入模块时出现了故障。在我看来,这似乎是一个错误。 - IanH
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模块,您需要确保调用该模块的init函数,在这种情况下为initmodule()。不幸的是,似乎在生成的头文件中没有声明此函数,因此我们需要在主函数上面手动添加它:
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

我已经复制了您的代码,但是在PyMODINIT_FUNC initmodule(void)initmodule()上出现了问题:“未定义符号架构x86_64: initmodule,引用自: ccSkO2qw.o中的_maininitmodule是否必须在其他地方实现,例如在module_api.h中? - richizy
然而,如果我删除 initmodule,我将复制相同的错误消息:ImportError: No module named module - richizy
@richizy,“initmodule”应该在从module.pyx生成的.cpp文件中定义。 - brm

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接