Question

I have two files module.pyx and foo.cpp. I want to be able to call a function, declared in the cython module module.pyx, within foo.cpp. This function returns a pointer to a 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;
}


I've compiled module.pyx with

cython module.pyx --cplus

and foo.cpp with

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

but it is not working. I get a huge error stating "vector in namespace 'std' does not name a type", among many other things. What is the problem?

I am using the Anaconda Python distribution, which I just did a recent clean & default install.

Versions:

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

Was it helpful?

Solution

To be able to use the python engine from a C or C++ application, you need to make sure that Py_Initialize() is called at the beginning of your main() function, and that Py_Finalize() is called at the end. What you also don't see is that the import_module() function actually produces an error, but it does this using the python error mechanism. You can make this visible by adding the following code below import_module():

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

If you do that, you'll see the following error appear:

ImportError: No module named module

To be able to use a Cython module, you have to make sure that that module's init function is called, in this case initmodule(). Unfortunatly it seems that the declaration of this function is not present in the generated header file, so we'll have to manually add it above the main:

PyMODINIT_FUNC initmodule(void);

Together with placing the vector include line first and a small fix in the cout line, the code then becomes:

#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;
}

Which, at least on my system, produces the output:

v[0] = 3
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top