3

I have a class named qwerty and a function called compute_ans inside it which takes a void pointer and returns a void pointer. Now when I try to compile, the following statement throws an error

pthread_create (thread_a, NULL, compute_ans, (void*) struct_left);

The definition of the function is void* compute_ans (void* struct_input)

The error is

cannot convert ‘qwerty::compute_ans’ from type ‘void* (qwerty::)(void*)’ to type ‘void* ()(void)’*

billz
  • 44,644
  • 9
  • 83
  • 100
x-treme
  • 1,606
  • 2
  • 21
  • 39

2 Answers2

3

You cannot convert a pointer to a non-static member function to a pointer to function, C++ does not allow it. The reason is that member functions take an implicit this pointer as a parameter. Essentially this changes the signature of your function to be something like void* compute_ans(qwerty*, void*). In order to pass the function to pthread_create you need to make the member function static.

class qwerty
{
public:
    // ... other member functions and variables ...

    // thread start function
    static void* compute_ans(void*);
};

If you cannot make this a static member function you will need to pass a pointer to a qwerty object to the thread start function. Looking at the code in your question you also need to pass additional data to the thread function. To do this you can use an additional data structure that contains all the necessary data and pass a pointer to that instead.

class qwerty;  // forward declaration

// Structure passed to pthread_create and our helper function
struct thread_data
{
    qwerty* qptr;   // pointer to qwerty object
    void*   data;   // pointer to other data. change void to your data type.
};

class qwerty
{
public:
    // thread start function
    static void* start_compute_ans(void* param)
    {
        // get a pointer to the thread data
        thread_data* tdata = static_cast<thread_data*>(param);

        // Call the real compute_ans
        tdata->qptr->compute_ans(tdata->data);

        // Delete the data (use an appropriate smart pointer if possible)
        delete tdata;

        return NULL;
    }

    // the real 
    void compute_ans(void*)
    {
        // do stuff here
    }
};

// Create our thread startup data
thread_data* tdata = new thread_data();
tdata->qptr = qwerty_pointer;
tdata->data = struct_left;

// start the thread data
pthread_create (thread_a, NULL, &qwerty::start_compute_ans, tdata);
Captain Obvlious
  • 19,754
  • 5
  • 44
  • 74
  • It is a pretty long application and if I convert the said function, I will have to convert every other function to static or create an object!! Is there a work around ? – x-treme Jun 24 '13 at 00:45
  • You don't have to do that. I'll update my answer with a solution for that scenario. May take a few though ;) – Captain Obvlious Jun 24 '13 at 00:49
  • Oh!! wait... Is that sarcasm ?! I have trying to decide on it for the past 10 mins and have finally concluded that it is!! I think I should go ahead and do it the longer way then.. :-( – x-treme Jun 24 '13 at 01:01
  • No, it's not sarcasm. I simply wanted to make sure everything was correct, compilable and working. Plus I wanted a Twinkie – Captain Obvlious Jun 24 '13 at 01:06
  • I guessed wrong!! You meant it. This solution rocks and so do you @Captain – x-treme Jun 24 '13 at 01:06
  • I looks like I need some more help. When I try to pass the class address to a pointer, the following error is thrown error: expected primary-expression before ‘;’ token I tried tdata->qptr = &qwerty and also tdata->qptr = qwerty. Neither works!! – x-treme Jun 24 '13 at 01:39
  • `qwerty` is a class type, you need to pass the address of an instance of `qwerty`. Something like `querty *qwerty_pointer = new qwerty(); tdata->qptr = qwerty_pointer;`. Make sure to properly delete it when you are done. – Captain Obvlious Jun 24 '13 at 01:44
  • +1 for good answer. I hope you enjoyed your Twinkie :) – Martin James Jun 24 '13 at 01:47
0

You can find the answer here.

You should use static functions to pass to pthread.

class qwerty
{
public:
    void compute_ans(void)
    {
        std::cout << "Compute result!" << std::endl;
        return
    }

    static void hello_helper(void *context)
    {
        return ((qwerty *)context)->compute_answer();
    }
};
...
qwerty c;
pthread_t t;
pthread_create(&t, NULL, &qwerty::hello_helper, &c);
Community
  • 1
  • 1
uncletall
  • 6,609
  • 1
  • 27
  • 52