Simple question: How to pass a C++ class reference to a callback?

H

Harri Pesonen

How do I pass the calling C++ class reference (or anything) to a callback?
My code is:

static PyObject*
emb_Set(PyObject *self, PyObject *args)
{
char *key, *value;
if(!PyArg_ParseTuple(args, "ss", &key, &value))
return NULL;
// do something with the C++ class here
// how the get the class instance pointer?
Py_INCREF(Py_None);
return Py_None;
}

static PyMethodDef EmbMethods[] = {
{"Set", emb_Set, METH_VARARGS, "Sets the given variable."},
{NULL, NULL, 0, NULL}
};

in C++ class:

Py_Initialize();
Py_InitModule("test", EmbMethods);
PyRun_SimpleString(script);
Py_Finalize();

Harri
 
T

T. Panbru

Try encapsulating your C++ class reference in a CObject, using:

PyObject* PyCObject_FromVoidPtr( void* cobj, void (*destr)(void *))
void* PyCObject_AsVoidPtr( PyObject* self)

and so forth, to go back and forth between the C++ and Python realms.

Check out the Python docs at:

http://www.python.org/doc/2.3/api/cObjects.html

Tim
 
D

David Abrahams

T. Panbru said:
Try encapsulating your C++ class reference in a CObject, using:

PyObject* PyCObject_FromVoidPtr( void* cobj, void (*destr)(void *))
void* PyCObject_AsVoidPtr( PyObject* self)

and so forth, to go back and forth between the C++ and Python realms.

Check out the Python docs at:

http://www.python.org/doc/2.3/api/cObjects.html

Or use one of the high-level wrapping tools such as Boost.Python
(http://www.boost.org/libs/python) which make this stuff much easier
and safer.
 
H

Harri Pesonen

I read it twice, but I'm not sure that I got it.

You mean that I add something like:

static PyObject*
emb_Set(PyObject *self, PyObject *args) {
char *key, *value;
if(!PyArg_ParseTuple(args, "ss", &key, &value))
return NULL;
// how the get the class instance pointer:
PyObject *c_api_object = PyObject_GetAttrString(self, "_C_API");
if (c_api_object) {
if (PyCObject_Check(c_api_object)) {
myClass *p = (myClass *)PyCObject_AsVoidPtr(c_api_object);

// do something with the C++ class here
}
Py_DECREF(c_api_object);
}
Py_INCREF(Py_None);
return Py_None;
}

And in C++ class:

Py_Initialize();
PyObject *m = Py_InitModule("test", EmbMethods);
// ??
PyObject *c_api_object = PyCObject_FromVoidPtr((void *)this, NULL);
if (c_api_object) {
PyModule_AddObject(m, "_C_API", c_api_object);
PyRun_SimpleString(script);
}
Py_Finalize();



T. Panbru said:
Try encapsulating your C++ class reference in a CObject, using:

PyObject* PyCObject_FromVoidPtr( void* cobj, void (*destr)(void *))
void* PyCObject_AsVoidPtr( PyObject* self)

and so forth, to go back and forth between the C++ and Python realms.

Check out the Python docs at:

http://www.python.org/doc/2.3/api/cObjects.html

Tim
Harri Pesonen wrote:
How do I pass the calling C++ class reference (or anything) to a
callback?
My code is:

static PyObject*
emb_Set(PyObject *self, PyObject *args)
{
char *key, *value;
if(!PyArg_ParseTuple(args, "ss", &key, &value))
return NULL;
// do something with the C++ class here
// how the get the class instance pointer?
Py_INCREF(Py_None);
return Py_None;
}

static PyMethodDef EmbMethods[] = {
{"Set", emb_Set, METH_VARARGS, "Sets the given variable."},
{NULL, NULL, 0, NULL}
};

in C++ class:

Py_Initialize();
Py_InitModule("test", EmbMethods);
PyRun_SimpleString(script);
Py_Finalize();

Harri
 
H

Harri Pesonen

I was close, but it appears that self is always NULL in embedded function (why?).

So the correct embedded function is

static PyObject*
emb_Set(PyObject *self, PyObject *args) {
char *key, *value;
if(!PyArg_ParseTuple(args, "ss", &key, &value))
return NULL;
// how the get the class instance pointer:
PyObject *m = PyImport_ImportModule("test");
if (m) {
PyObject *c_api_object = PyObject_GetAttrString(m, "_C_API");
if (c_api_object) {
myClass *p = (myClass *)PyCObject_AsVoidPtr(c_api_object);
// do something with the C++ class here
Py_DECREF(c_api_object);
}
Py_DECREF(m);
}
Py_INCREF(Py_None);
return Py_None;
}

Harri Pesonen said:
I read it twice, but I'm not sure that I got it.

You mean that I add something like:

static PyObject*
emb_Set(PyObject *self, PyObject *args) {
char *key, *value;
if(!PyArg_ParseTuple(args, "ss", &key, &value))
return NULL;
// how the get the class instance pointer:
PyObject *c_api_object = PyObject_GetAttrString(self, "_C_API");
if (c_api_object) {
if (PyCObject_Check(c_api_object)) {
myClass *p = (myClass *)PyCObject_AsVoidPtr(c_api_object);

// do something with the C++ class here
}
Py_DECREF(c_api_object);
}
Py_INCREF(Py_None);
return Py_None;
}

And in C++ class:

Py_Initialize();
PyObject *m = Py_InitModule("test", EmbMethods);
// ??
PyObject *c_api_object = PyCObject_FromVoidPtr((void *)this, NULL);
if (c_api_object) {
PyModule_AddObject(m, "_C_API", c_api_object);
PyRun_SimpleString(script);
}
Py_Finalize();



T. Panbru said:
Try encapsulating your C++ class reference in a CObject, using:

PyObject* PyCObject_FromVoidPtr( void* cobj, void (*destr)(void *))
void* PyCObject_AsVoidPtr( PyObject* self)

and so forth, to go back and forth between the C++ and Python realms.

Check out the Python docs at:

http://www.python.org/doc/2.3/api/cObjects.html

Tim
Harri Pesonen wrote:
How do I pass the calling C++ class reference (or anything) to a
callback?
My code is:

static PyObject*
emb_Set(PyObject *self, PyObject *args)
{
char *key, *value;
if(!PyArg_ParseTuple(args, "ss", &key, &value))
return NULL;
// do something with the C++ class here
// how the get the class instance pointer?
Py_INCREF(Py_None);
return Py_None;
}

static PyMethodDef EmbMethods[] = {
{"Set", emb_Set, METH_VARARGS, "Sets the given variable."},
{NULL, NULL, 0, NULL}
};

in C++ class:

Py_Initialize();
Py_InitModule("test", EmbMethods);
PyRun_SimpleString(script);
Py_Finalize();

Harri
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,051
Latest member
CarleyMcCr

Latest Threads

Top