1

在这里,我为 c 线程函数编写了一个线程包装器pthread_create()。它将允许在任何对象上调用任何方法并将任意数量的参数传递给该方法。API 是:

template <typename T, typename R, typename... ATs>
pthread_t NewThread(T *obj, R (T::*mem)(ATs...), ATs... args);

下面是模板:

template<unsigned int i>  
class TupleUnpack 
{
    public:
    template<typename R, typename ...ATs, typename ...T_function_arguments>
    inline static R unpack (R  (*function) (ATs...), 
    std::tuple<ATs...> arguments_tuple,
    T_function_arguments  ...function_arguments)
    {
        return TupleUnpack<i-1>::unpack (function, arguments_tuple, std::get<i-1> (arguments_tuple), function_arguments...);
    }                       
};

template<> 
class TupleUnpack<0> 
{
    public:
    template<typename R, typename ...ATs, typename ...T_function_arguments>
    inline static R unpack (R                (*function) (ATs...), 
    std::tuple<ATs...> arguments_tuple,
    T_function_arguments              ...function_arguments)
    {
        return function (function_arguments...);
    }          
};
class CallCaller
{   
    virtual bool dispatch (void)=0;
};

template<typename T,typename R,typename ...ATs> 
class Call : public CallCaller
{
    public:     
    Call (T *obj,R (*function) (ATs...),ATs... arguments) :obj(obj),function (function),tuplearg (arguments...) {}

    ~Call() {}
    bool dispatch (void)
    {
        return TupleUnpack<sizeof ...(ATs)>::unpack (this->function, this->tuplearg);
    }

    private:
    std::tuple<ATs...> tuplearg;
    R (*function) (ATs...);

    T *obj;
};

void *test(int d,double sf)
{
    std::cout<<"yay my thread runs d="<<d<<" sf="<<sf<<std::endl;       
}

template<typename T,typename R,typename ...ATs> 
void* stub (void* vp)
{

    Call<T,R,ATs...>* call = static_cast<Call<T,R,ATs...>*>(vp);
    call->dispatch();       
    delete call;        
    pthread_exit (0);

}
template <typename T, typename R, typename... ATs>
pthread_t NewThread(T *ob, R (T::*mem)(ATs...), ATs... args)
{
    pthread_t tid;
    R (*func) (ATs...);
    Call<T,R,ATs...> *task=new Call<T,R,ATs...>(ob,&test,args...);

    pthread_create(&tid, nullptr, stub<T,R,ATs...>, task) ;

    return tid;
}

以下是 CPP 文件:

#include <tr1/tuple>
#include <utility>
#include <iostream>
#include <pthread.h>
#include <tuple>
#include <type_traits>
#include <utility>
#include "NewThread.hpp"

class X
{
    public:
    void *method(int a, double x)
    {
        std::cout<<"yay my tread runs a="<<a<<" x="<<x<<std::endl;
    }

};

int main()
{
    X x;
    int i;
    pthread_t tid = NewThread(&x, &X::method, 1234, 3.14);



    pthread_join(tid,NULL);

    std::cout<<"Thread Ended "<<tid<<std::endl;
    return 0;
}

我正在尝试x::method()使用参数调用。正如你所看到的,我有一个test()类似于x::method()只是为了证明我的线程正在工作的函数。但我希望能够调用x::method(). 有人可以指导我吗?

本质上,我当前的输出是:

yay my thread runs d=1234 sf=3.14
Thread Ended 139766222432000

我希望我的输出是

yay my thread runs a=1234 x=3.14
Thread Ended 139766222432000
4

1 回答 1

1

所以这

R (*function) (ATs...);

是一个函数指针,但是你需要一个成员函数指针

R (T::*function) (ATs...);

要调用成员函数指针,您需要一个对象,并且必须使用以下语法调用它:

self->*function(function_arguments...);

注意->*这里的语法。

所以我添加了一个T* self参数并用成员TupleUnpack<>::unpack调用它。现在,我可以将函数替换为.Call<>::dispatchobjtestmemNewThread

这是一个补丁:

diff --git a/NewThread.hpp b/NewThread.hpp
index e121294..768f7d9 100644
--- a/NewThread.hpp
+++ b/NewThread.hpp
@@ -5,12 +5,12 @@ template<unsigned int i>
 class TupleUnpack 
 {
     public:
-    template<typename R, typename ...ATs, typename ...T_function_arguments>
-    inline static R unpack (R  (*function) (ATs...), 
+    template<typename T, typename R, typename ...ATs, typename ...T_function_arguments>
+    inline static R unpack (T* self, R (T::*function) (ATs...), 
     std::tuple<ATs...> arguments_tuple,
     T_function_arguments  ...function_arguments)
     {
-        return TupleUnpack<i-1>::unpack (function, arguments_tuple, std::get<i-1> (arguments_tuple), function_arguments...);
+        return TupleUnpack<i-1>::unpack (self, function, arguments_tuple, std::get<i-1> (arguments_tuple), function_arguments...);
     }                       
 };

@@ -18,12 +18,12 @@ template<>
 class TupleUnpack<0> 
 {
     public:
-    template<typename R, typename ...ATs, typename ...T_function_arguments>
-    inline static R unpack (R                (*function) (ATs...), 
+    template<typename T, typename R, typename ...ATs, typename ...T_function_arguments>
+    inline static R unpack (T* self, R (T::*function) (ATs...), 
     std::tuple<ATs...> arguments_tuple,
     T_function_arguments              ...function_arguments)
     {
-        return function (function_arguments...);
+        return (self->*function) (function_arguments...);
     }          
 };
 class CallCaller
@@ -35,19 +35,17 @@ template<typename T,typename R,typename ...ATs>
 class Call : public CallCaller
 {
     public:     
-    Call (T *obj,R (*function) (ATs...),ATs... arguments) :obj(obj),function (function),tuplearg (arguments...) {}
+    Call (T *obj,R (T::*function) (ATs...),ATs... arguments) :obj(obj),function (function),tuplearg (arguments...) {}

     ~Call() {}
     bool dispatch (void)
     {
-        return TupleUnpack<sizeof ...(ATs)>::unpack (this->function, this->tuplearg);
+        return TupleUnpack<sizeof ...(ATs)>::unpack(obj, this->function, this->tuplearg);
     }

     private:
     std::tuple<ATs...> tuplearg;
-    R (*function) (ATs...);
+    R (T::*function) (ATs...);

     T *obj;
 };
@@ -71,8 +69,7 @@ template <typename T, typename R, typename... ATs>
 pthread_t NewThread(T *ob, R (T::*mem)(ATs...), ATs... args)
 {
     pthread_t tid;
-    R (*func) (ATs...);
-    Call<T,R,ATs...> *task=new Call<T,R,ATs...>(ob,&test,args...);
+    Call<T,R,ATs...> *task=new Call<T,R,ATs...>(ob,mem,args...);

     pthread_create(&tid, nullptr, stub<T,R,ATs...>, task) ;
于 2013-05-12T01:57:28.483 回答