B. Barbieri
B. Barbieri

Reputation: 1139

Using cython cdef public variable in c++ : variable is never initialized

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

Upvotes: 0

Views: 416

Answers (1)

spectras
spectras

Reputation: 13542

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.

Upvotes: 2

Related Questions