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

Charles Solar charlessolar at gmail.com
Sat Jul 3 01:27:39 CEST 2010


Threads and python do not mix very well.  You need to handle locking and
unlocking the gil at the boundaries of python and c++.
There are several posts here about this problem, just search for thread or
'no current thread' in the archives.
A month ago I posted a modified boost python that will handle the gil
correctly for you if you want to give that a shot, or there is also TnFox
which also handles threads correctly.

Basically the short answer to your question is that you most certainly can,
but you need to understand how the gil works and when and where you need to
have it in order to do it correctly.

On Fri, Jul 2, 2010 at 5:29 PM, Anton Yabchinskiy <arn at bestmx.ru> wrote:

> 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);
>
> }
> _______________________________________________
> Cplusplus-sig mailing list
> Cplusplus-sig at python.org
> http://mail.python.org/mailman/listinfo/cplusplus-sig
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/cplusplus-sig/attachments/20100702/804bf7ae/attachment-0001.html>


More information about the Cplusplus-sig mailing list