2

次のコードを使用して、C++ でスレッドを作成しようとしています。

pthread_t mythread;
void* f (void*) = MyClass::myfunction;
pthread_create(&mythread, NULL, &f, NULL);

動いていない。何が問題なのですか?

myfunction のタイプは次のとおりです。

void* MyClass::myfunction(void* argv);

返されるエラーは次のとおりです。

error: declaration of ‘void* Class::f(void*)’ has ‘extern’ and is initialized

error: invalid pure specifier (only ‘= 0’ is allowed) before ‘::’ token

error: function ‘void* Class::f(void*)’ is initialized like a variable
4

3 に答える 3

6

f関数ポインタではなく関数として宣言しています。そのはず:

void* (*f) (void*) = &MyClass::myfunction;
      ^^^^

pthread_create(&mythread, NULL, f, NULL);
                                ^ no & since it's already a pointer

myfunctionメンバー関数へのポインターを関数へのポインターに変換できないため、これは静的な場合にのみ機能します。

特定のオブジェクトで非静的メンバー関数を実行するためにスレッドが必要な場合、1 つの方法は、オブジェクトを引数として受け取る静的ラッパーを作成することです。

class MyClass {
public:
    void start_thread() {
        // Pass "this" to the thread we're creating
        pthread_create(&mythread, NULL, &MyClass::thread_entry, this);
    }
private:
    static void * thread_entry(void * object) {
        // Call the member function on the object passed to the thread
        return static_cast<MyClass*>(object)->thread();
    }
    void * thread() {
        // do the interesting stuff, with access to the member variables
    }
};

もちろん、最近では、このダンスの必要性をなくす標準のスレッド ライブラリがあります。

std::thread thread(&MyClass::thread, this);
于 2012-07-04T10:42:18.353 に答える
2

Pthreads は関数ポインターを想定しており、クラスでは、関数ポインターを使用してのみ静的メソッドを指すことができます。

特定のオブジェクトでクラスの特定のメソッドを呼び出したい場合は、データの 2 つの別個の部分が必要です。

  • クラス メソッドへのポインタ (関数ポインタと混同しないでください)
  • オブジェクトへのポインタ

これら 2 つを結合して、非公式にデリゲートと呼ぶことができます。


PThreads は C ライブラリであり、それと相互運用するには、少し回避策が必要です。

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
    void *(*start_routine)(void*),
    void *arg);

クラス メソッドを static クラス メソッドでラップして、それを parameter として渡すことができるようにstart_routineし、オブジェクト自体へのポインタを として渡しますarg

コードを参照してください:

struct Foo {

    // wrapper method
    static void* threadStartingPoint(void* obj) {
        return ((Foo)obj)->threadFunc();
    }

    // your target method itself
    void* threadFunc() {
        // this is where you do your logic
    }
}

このような回避策により、 を使用できますpthread_create(thread, attr, Foo::threadStartingPoint, someObject)


幸運にも をサポートする最新のコンパイラをstd::thread使用できる場合は、pthreads の代わりにそれを使用して、コードをより単純にすることができます。std::functionオブジェクトを作成して、それをstd::threadのコンストラクタに渡すだけです。

于 2012-07-04T10:47:05.823 に答える
1

あなたがやろうとしていることを単純に行うことはできません-メンバー関数(静的でない限り)には、呼び出されるオブジェクトが必要です-つまり、スレッドを開始するプロセスは MyClass::f() を呼び出すことはできません。 something.f() を呼び出す必要がありますが、それが何であるかはわかりません。

通常、オブジェクトをパラメーターとして受け取り、そのオブジェクトでメンバー関数を呼び出す静的メンバー関数を定義することで、これを回避します。

于 2012-07-04T10:42:07.323 に答える