I think the Putin way is to allow various extensions to interact through the C API. Although I am not very good at C ++, I assume that this is not so different from the solution in C. I would do it like this:
- define a global variable in module A
- define a C API for module A, which contains a pointer to a global variable (and a macro for convenience, if you wish).
- load API C into module B and access the global variable with a pointer.
Writing the C API for python C extensions is a bit related. (Read the python docs on the Python C API if you are not familiar with it.) A minimal example of my proposed solution would look like this:
Ah
#ifndef A_MODULE_H #define A_MODULE_H #ifdef __cplusplus extern "C" { #endif #define PyA_GET_X() (*x_ptr) #define PyA_SET_X(x) (*x_ptr = x) #ifdef A_MODULE #else static void **PyA_API; #define x_ptr ((long *)PyA_API[0]) static int import_A(void) { PyA_API = (void **)PyCapsule_Import("A._C_API", 0); return (PyA_API != NULL) ? 0 : -1; } #endif #ifdef __cplusplus } #endif #endif
Ac
#include <Python.h> #define A_MODULE #include "Ah" long x = 0; /* here is the global variable */ static PyObject* set_x(PyObject *self, PyObject *args){ if (!PyArg_ParseTuple(args, "l", &x)) return NULL; Py_RETURN_NONE; } static PyObject* get_x(PyObject *self, PyObject *args){ return PyInt_FromLong(x); } static PyMethodDef methods[] = { {"set_x", (PyCFunction)set_x, METH_VARARGS, ""}, {"get_x", (PyCFunction)get_x, METH_NOARGS, ""}, {NULL, NULL, 0, NULL} }; #ifndef PyMODINIT_FUNC /* declarations for DLL import/export */ #define PyMODINIT_FUNC void #endif PyMODINIT_FUNC initA(void){ PyObject *m = Py_InitModule3("A", methods, ""); static void *PyA_API[1]; PyA_API[0] = (void *)&x; PyObject *c_api_object = PyCapsule_New((void *)PyA_API, "A._C_API", NULL); if (c_api_object != NULL) PyModule_AddObject(m, "_C_API", c_api_object); }
Bc
#include <Python.h> #define B_MODULE #include "Ah" static PyObject* set_x(PyObject *self, PyObject *args){ long y; if (!PyArg_ParseTuple(args, "l", &y)) return NULL; PyA_SET_X(y); Py_RETURN_NONE; } static PyObject* get_x(PyObject *self, PyObject *args){ return PyInt_FromLong(PyA_GET_X()); } static PyMethodDef methods[] = { {"set_x", (PyCFunction)set_x, METH_VARARGS, ""}, {"get_x", (PyCFunction)get_x, METH_NOARGS, ""}, {NULL, NULL, 0, NULL} }; #ifndef PyMODINIT_FUNC /* declarations for DLL import/export */ #define PyMODINIT_FUNC void #endif PyMODINIT_FUNC initB(void){ import_A(); Py_InitModule3("B", methods, ""); }
setup.py
from numpy.distutils.core import setup, Extension setup( name="AB", ext_modules = [Extension('A', ['A.c']), Extension('B', ['B.c'])], )
and finally, you can read and modify x from both modules, starting at the C or python level. In python, it will look like this:
>>> import A, B >>> A.set_x(1) >>> B.get_x() 1 >>> B.set_x(2) >>> A.get_x() 2
for access from level C use the macros PyA_GET_X() and PyA_SET_X(x) .