[C++-sig] X-language polymorphism and multithreading

Anton Yabchinskiy arn at bestmx.ru
Sat Jul 3 00:29:29 CEST 2010


Hi there.

I'm unsuccessfully trying to do a weird thing: to call an overridden
method in Python's class from a C++ thread. It doesn't work neither
with SWIG nor with Boost.Python. And I don't really sure it is
possible. Can someone comment on this? Below is the forwarded message
from the SWIG mailing list.

----- Forwarded message from Nitro <nitro at dr-code.org> -----

Am 01.07.2010, 22:35 Uhr, schrieb Anton Yabchinskiy <arn at bestmx.ru>:

> Greetings, SWIG users.
>
> Is it any way one could pass some data from the spawned thread in C++
> code to the Python class' method? My interface file looks like this:
>
> %module(directors="1") xyzzy
>
> %include <std_vector.i>
>
> %{
> #include "xyzzy.hpp"
> %}
>
> %template(Data_Buffer) std::vector<char>;
>
> namespace xyzzy {
>
>     typedef std::vector<char> Data_Buffer;
>
>     // Data listener interface
>     %feature("director") Data_Listener;
>     class Data_Listener
>     {
>     public:
>         virtual
>         ~Data_Listener();
>
>         virtual void
>         on_data(const Data_Buffer& data);
>     };
>
>     // Has an internal thread running
>     class Data_Provider
>     {
>     public:
>         // Add the listener to the list of known listeners. Call
>         // listener's “on_data” method from internal thread when a
>         // block of data becomes available.
>         int
>         start(Data_Listener& listener);
>
>         // Removes the listener from the internal list of active
>         // listeners.
>         void
>         stop(int ticket);
>     };
>
> }// namespace xyzzy
>
> Interface file is then get processed and compiled into extension:
> $ swig -c++ -python -o _xyzzy.cpp xyzzy.i
> $ g++ -Wall -W -O1 -g `python2.5-dbg-config --includes` *.cpp -shared -o  
> _xyzzy.so -lPocoFoundation
>
> Then I'm trying to run a test application:
>
> #!/usr/bin/python2.5-dbg
>
> import time
> import xyzzy
>
> class Listener(xyzzy.Data_Listener):
>     def __init__(self):
>         xyzzy.Data_Listener.__init__(self)
>
>     def on_data(self, data):
>         print "data =", data
>
> provider = xyzzy.Data_Provider()
> listener = Listener()
> n = provider.start(listener)
> time.sleep(10)
> provider.stop(n)
>
> And before “on_data” method get called it aborts with the following:
>
> Fatal Python error: PyThreadState_Get: no current thread
> [1]    14018 abort      ./test.py
>
> It seems to work (but SIGSEGVs on exit), if sleep is replaced with
> simple infinite loop:
>
> while True:
>     pass
>
> Is it something I missing? Is it something could be tweaked in the
> generated interfacing code? Or is it not possible to do such a thing?
>
> Thanks in advance for any suggestions and comments.

I think this question is better asked on the Python list. It might be  
something like time.sleep() not releasing the GIL and then sleeping. Or  
you might have to call things like PyThreadState_New(). The guys on the  
python list should be able to give you some answers.

-Matthias

----- End forwarded message -----

Also here is my Boost.Python file:

#include <boost/python.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>

#include "../xyzzy.hpp"

using namespace boost::python;
using namespace xyzzy;

class Data_Listener_Wrapper : public Data_Listener, public wrapper<Data_Listener>
{
public:
    void
    on_data(const Data_Buffer& data)
    {
        if (override on_data = get_override("on_data")) {
            on_data(data);
        }
        default_on_data(data);
    }

    void
    default_on_data(const Data_Buffer& data)
    {
        Data_Listener::on_data(data);
    }
};

BOOST_PYTHON_MODULE(xyzzy) {

    class_<Data_Buffer>("Data_Buffer")
        .def(vector_indexing_suite<Data_Buffer>());

    class_<Data_Listener_Wrapper, boost::noncopyable>("Data_Listener")
        .def("on_data", &Data_Listener::on_data, &Data_Listener_Wrapper::default_on_data);

    class_<Data_Provider, boost::noncopyable>("Data_Provider")
        .def("start", &Data_Provider::start)
        .def("stop", &Data_Provider::stop);

}


More information about the Cplusplus-sig mailing list