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

Discussion in 'Python' started by Harri Pesonen, Sep 2, 2003.

  1. 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
    Harri Pesonen, Sep 2, 2003
    #1
    1. Advertising

  2. Harri Pesonen

    T. Panbru Guest

    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
    T. Panbru, Sep 2, 2003
    #2
    1. Advertising

  3. Re: Simple question: How to pass a C++ class reference to acallback?

    "T. Panbru" <> writes:

    > 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.

    --
    Dave Abrahams
    Boost Consulting
    www.boost-consulting.com
    David Abrahams, Sep 2, 2003
    #3
  4. David Abrahams wrote:
    > "T. Panbru" <> writes:
    >
    >>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.


    Boost.Python is not 2.3 compatible yet, but it seems very good.

    Harri
    Harri Pesonen, Sep 2, 2003
    #4
  5. 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 wrote:

    > 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

    >
    >
    Harri Pesonen, Sep 2, 2003
    #5
  6. 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 <> wrote in message news:<lj45b.2298$>...
    > 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 wrote:
    >
    > > 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

    > >
    > >
    Harri Pesonen, Sep 3, 2003
    #6
  7. Re: Simple question: How to pass a C++ class reference to acallback?

    Harri Pesonen <> writes:

    > David Abrahams wrote:
    >> "T. Panbru" <> writes:
    >>
    >>>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.

    >
    > Boost.Python is not 2.3 compatible yet, but it seems very good.


    The CVS version is 2.3 compatible; you can download a snapshot from
    http://www.boost-consulting.com/boost.tar.bz2 or you can access our
    anonymous CVS or a mirror (about a day behind).

    --
    Dave Abrahams
    Boost Consulting
    www.boost-consulting.com
    David Abrahams, Sep 3, 2003
    #7
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Jerry
    Replies:
    20
    Views:
    7,930
    Roedy Green
    Sep 9, 2005
  2. blufox
    Replies:
    2
    Views:
    551
  3. Mr A
    Replies:
    111
    Views:
    2,108
  4. Robert
    Replies:
    10
    Views:
    1,367
    E. Robert Tisdale
    Aug 24, 2005
  5. LuB
    Replies:
    6
    Views:
    452
    Mike Wahler
    Sep 23, 2005
Loading...

Share This Page