pthread function from a class

2018-12-31 04:57发布

Let's say I have a class such as

class c { 
    // ...
    void *print(void *){ cout << "Hello"; }
}

And then I have a vector of c

vector<c> classes; pthread_t t1;
classes.push_back(c());
classes.push_back(c());

Now, I want to create a thread on c.print();

And the following is giving me the problem below: pthread_create(&t1, NULL, &c[0].print, NULL);

Error Ouput: cannot convert ‘void* (tree_item::)(void)’ to ‘void* ()(void)’ for argument ‘3’ to ‘int pthread_create(pthread_t*, const pthread_attr_t*, void* ()(void), void*)’

标签: c++ pthreads
8条回答
其实,你不懂
2楼-- · 2018-12-31 05:17

My favorite way to handle a thread is to encapsulate it inside a C++ object. Here's an example:

class MyThreadClass
{
public:
   MyThreadClass() {/* empty */}
   virtual ~MyThreadClass() {/* empty */}

   /** Returns true if the thread was successfully started, false if there was an error starting the thread */
   bool StartInternalThread()
   {
      return (pthread_create(&_thread, NULL, InternalThreadEntryFunc, this) == 0);
   }

   /** Will not return until the internal thread has exited. */
   void WaitForInternalThreadToExit()
   {
      (void) pthread_join(_thread, NULL);
   }

protected:
   /** Implement this method in your subclass with the code you want your thread to run. */
   virtual void InternalThreadEntry() = 0;

private:
   static void * InternalThreadEntryFunc(void * This) {((MyThreadClass *)This)->InternalThreadEntry(); return NULL;}

   pthread_t _thread;
};

To use it, you would just create a subclass of MyThreadClass with the InternalThreadEntry() method implemented to contain your thread's event loop. You'd need to call WaitForInternalThreadToExit() on the thread object before deleting the thread object, of course (and have some mechanism to make sure the thread actually exits, otherwise WaitForInternalThreadToExit() would never return)

查看更多
浅入江南
3楼-- · 2018-12-31 05:17

C++ : How to pass class member function to pthread_create()?

http://thispointer.com/c-how-to-pass-class-member-function-to-pthread_create/

typedef void * (*THREADFUNCPTR)(void *);

class C { 
   // ...
   void *print(void *) { cout << "Hello"; }
}

pthread_create(&threadId, NULL, (THREADFUNCPTR) &C::print, NULL);
查看更多
笑指拈花
4楼-- · 2018-12-31 05:18

My first answer ever in the hope that it'll be usefull to someone : I now this is an old question but I encountered exactly the same error as the above question as I'm writing a TcpServer class and I was trying to use pthreads. I found this question and I understand now why it was happening. I ended up doing this:

#include <thread>

method to run threaded -> void* TcpServer::sockethandler(void* lp) {/*code here*/}

and I call it with a lambda -> std::thread( [=] { sockethandler((void*)csock); } ).detach();

that seems a clean approach to me.

查看更多
旧人旧事旧时光
5楼-- · 2018-12-31 05:20

The above answers are good, but in my case, 1st approach that converts the function to be a static didn't work. I was trying to convert exiting code to move into thread function but that code had lots to references to non-static class members already. The second solution of encapsulating into C++ object works, but has 3-level wrappers to run a thread.

I had an alternate solution that uses existing C++ construct - 'friend' function, and it worked perfect for my case. An example of how I used 'friend' (will use the above same example for names showing how it can be converted into a compact form using friend)

    class MyThreadClass
    {
    public:
       MyThreadClass() {/* empty */}
       virtual ~MyThreadClass() {/* empty */}

       bool Init()
       {
          return (pthread_create(&_thread, NULL, &ThreadEntryFunc, this) == 0);
       }

       /** Will not return until the internal thread has exited. */
       void WaitForThreadToExit()
       {
          (void) pthread_join(_thread, NULL);
       }

    private:
       //our friend function that runs the thread task
       friend void* ThreadEntryFunc(void *);

       pthread_t _thread;
    };

    //friend is defined outside of class and without any qualifiers
    void* ThreadEntryFunc(void *obj_param) {
    MyThreadClass *thr  = ((MyThreadClass *)obj_param); 

    //access all the members using thr->

    return NULL;
    }

Ofcourse, we can use boost::thread and avoid all these, but I was trying to modify the C++ code to not use boost (the code was linking against boost just for this purpose)

查看更多
唯独是你
6楼-- · 2018-12-31 05:23

My guess would be this is b/c its getting mangled up a bit by C++ b/c your sending it a C++ pointer, not a C function pointer. There is a difference apparently. Try doing a

(void)(*p)(void) = ((void) *(void)) &c[0].print; //(check my syntax on that cast)

and then sending p.

I've done what your doing with a member function also, but i did it in the class that was using it, and with a static function - which i think made the difference.

查看更多
浅入江南
7楼-- · 2018-12-31 05:31

You'll have to give pthread_create a function that matches the signature it's looking for. What you're passing won't work.

You can implement whatever static function you like to do this, and it can reference an instance of c and execute what you want in the thread. pthread_create is designed to take not only a function pointer, but a pointer to "context". In this case you just pass it a pointer to an instance of c.

For instance:

static void* execute_print(void* ctx) {
    c* cptr = (c*)ctx;
    cptr->print();
    return NULL;
}


void func() {

    ...

    pthread_create(&t1, NULL, execute_print, &c[0]);

    ...
}
查看更多
登录 后发表回答