0

I'm trying to translate some simple cython to c++ :

cdef public int G = 1

and then use it in my c++ code :

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

Output is :

G : 0

I've looked into the test.cpp cython-generated file, and on line 897, I have

  G = 1;

So why is G evaluated to 0 in the main ?

Here are the commands used to compile :

cython.exe test.pyx -3 --cplus
g++ test.cpp test_main.cpp -IC:\Python36-32\include -LC:\Python36-32\libs -lpython36
2
  • How do you compile and link your program? As given, it won't link. Commented Apr 21, 2017 at 12:39
  • @spectras edited. I used this answer to get help with linking. Commented Apr 21, 2017 at 12:44

1 Answer 1

2

What you generate when you use cython is a python extension module. You cannot link it directly into an executable, as it needs to be dynamically imported and linked to libpython. In that process, your extension's initialization function is run, which will cause your G to be set to 1.

So you should:

  • Build a python extension from your cython (using -shared and outputting a DLL).
  • Load python interpreter in your main. In your program, you don't even initialize python at the moment.
  • Import it in your main using PyImport_ImportModule("mymodule").

Untested, but your main should look like this:

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

You can get G from python using PyObject_GetAttrString(), or since you declared it as cdef, you can access it directly using your OS's symbol resolution tools, such as GetProcAddress() for windows.

It may be possible to link dynamically at load time, yet still use importmodule to let python do its initialization magic, but I have no idea how to do that or if it's even possible.

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for your answer. It feels like a lot more complicated than what I expected ... I've done the same thing for a function, and everything was just fine without importing the module, only calling Py_Initialize and Py_Finalize
The Cython documentation specifies a couple of different way of doing import/initialization which you might find slightly simpler. The basic idea is very much the same as this answer though.
@DavidW Just perfect. G is 1 after a call to PyInit_test (because i'm using python3, the documentation you provided has examples for python2)
@B.Barbieri> great! Yeah now you mention it, this is what ImportModule does: it looks for PyInit_modulename inside the module and calls it. So if you do it yourself it should replace the DLL + importmodule just fine.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.