Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Embedding matplotlib in C++

I am reading a message from a socket with C++ code and am trying to plot it interactively with matplotlib, but it seems Python code will block the main thread, no matter I use show() or ion() and draw(). ion() and draw() won't block in Python.

Any idea how to plot interactively with matplotlib in C++ code?

An example would be really good.

Thanks a lot.

like image 944
bbc Avatar asked Apr 11 '12 16:04

bbc


1 Answers

You may also try creating a new thread that does the call to the blocking function, so that it does not block IO in your main program loop. Use an array of thread objects and loop through to find an unused one, create a thread to do the blocking calls, and have another thread that joins them when they are completed.

This code is a quick slap-together I did to demonstrate what I mean about using threads to get pseudo asynchronous behavior for blocking functions... I have not compiled it or combed over it very well, it is simply to show you how to accomplish this.

#include <pthread.h>
#include <sys/types.h>
#include <string>
#include <memory.h>
#include <malloc.h>
#define MAX_THREADS 256 // Make this as low as possible!
using namespace std;
pthread_t PTHREAD_NULL;
typedef string someTypeOrStruct;
class MyClass
{
    typedef struct
    {
        int id;
        MyClass *obj;
        someTypeOrStruct input;
    } thread_data;

    void draw();    //Undefined in this example
    bool getInput(someTypeOrStruct *);  //Undefined in this example
    int AsyncDraw(MyClass * obj, someTypeOrStruct &input);
    static void * Joiner(MyClass * obj);
    static void * DoDraw(thread_data *arg);
    pthread_t thread[MAX_THREADS], JoinThread;
    bool threadRunning[MAX_THREADS], StopJoinThread;

    bool exitRequested;
public:
    void Main();
};

bool MyClass::getInput(someTypeOrStruct *input)
{
}

void MyClass::Main()
{
    exitRequested = false;
    pthread_create( &JoinThread, NULL, (void *(*)(void *))MyClass::Joiner, this);

    while(!exitRequested)
    {
        someTypeOrStruct tmpinput;
        if(getInput(&tmpinput))
            AsyncDraw(this, tmpinput);
    }

    if(JoinThread != PTHREAD_NULL)
    {
        StopJoinThread = true;
        pthread_join(JoinThread, NULL);
    }
}

void *MyClass::DoDraw(thread_data *arg)
{
    if(arg == NULL) return NULL;
    thread_data *data = (thread_data *) arg;
    data->obj->threadRunning[data->id] = true;
    // -> Do your draw here <- //
    free(arg);
    data->obj->threadRunning[data->id] = false; // Let the joinThread know we are done with this handle...
}

int MyClass::AsyncDraw(MyClass *obj, someTypeOrStruct &input)
{
    int timeout = 10; // Adjust higher to make it try harder...
    while(timeout)
    {
        for(int i = 0; i < MAX_THREADS; i++)
        {
            if(thread[i] == PTHREAD_NULL)
            {
                thread_data *data = (thread_data *)malloc(sizeof(thread_data));
                if(data)
                {
                    data->id = i;
                    data->obj = this;
                    data->input = input;

                    pthread_create( &(thread[i]), NULL,(void* (*)(void*))MyClass::DoDraw, (void *)&data);
                    return 1;
                }
                return 0;
            }
        }
        timeout--;
    }
}

void *MyClass::Joiner(MyClass * obj)
{
    obj->StopJoinThread = false;
    while(!obj->StopJoinThread)
    {
        for(int i = 0; i < MAX_THREADS; i++)
            if(!obj->threadRunning[i] && obj->thread[i] != PTHREAD_NULL)
            {
                pthread_join(obj->thread[i], NULL);
                obj->thread[i] = PTHREAD_NULL;
            }
    }
}

int main(int argc, char **argv)
{
    MyClass base;
    base.Main();
    return 0;
}

This way you can continue accepting input while the draw is occurring.

~~Fixed so the above code actually compiles, make sure to add -lpthread

like image 192
miigotu Avatar answered Nov 09 '22 06:11

miigotu