4

関数を別の関数の引数として渡す方法を知っています。しかし、pthread に渡される関数の引数が別の関数になるかどうかはわかりません。これは可能ですか?

以下は、コンパイルは成功するが動作しないサンプル コードです。

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

pthread_t idThread;

void aFunction(){
    while(1){
        fprintf(stderr,"I've been called!\n");
        usleep(1000000);
    }
}

void * threadFunction(void *argFunc){
    // Do here some stuff;
    // ...

    // Now call the function passed as argument
    void (*func)() = argFunc;
}    

int thread_creator(void(*f)()){
    // I want to use as argument for threadFunction the f function
    pthread_create(&idThread, NULL, threadFUnction, (void *)f);
}

int main(){
    thread_creator(aFunction);
    while(1);
    return 0;
}
4

4 に答える 4

7

ルールを少し曲げたい場合は、関数ポインターにすることができます。厳密に言えばvoid *、関数ポインタを保持できることは保証されていません。このようなもの(テストされていません):

void some_fun()
{
    /* ... */
}

void thread_fun(void *arg)
{
    void (*fun)() = arg;
}

pthread_create(...., (void *) some_fun);

編集

あなたの例では、関数ポインタを介して関数を呼び出す必要もあります。何かのようなもの:

void (*func)() = argFunc;
funct(); /* <-- */
于 2012-09-12T16:02:45.120 に答える
3

すでに与えられた答えに追加するには:

概念的には、関数ポインターは他のタイプのポインターと同じように渡すことができますが、指摘されているようにvoid *、a は関数ポインターを保持するのに十分な大きさであることが保証されておらず、データ ポインターのみです。

コールバック関数のようなものの回避策はpthread_create、ユーザー データとして使用する構造体で目的の関数ポインターをラップすることです。

struct threadArg
{
    void (*callback)(void);
};

// ...
struct threadArg *threadArg = malloc(sizeof(threadArg));
threadArg->callback = myFunction;
pthread_create(&idThread, NULL, threadFunction, (void *) threadArg);
于 2012-09-12T16:49:22.843 に答える
3

厳密に言えば、それは不可能です。標準によれば、へのvoidポインターは、オブジェクト型へのポインターへの変換、またはポインターからオブジェクト型への変換のみが可能です。一部のアーキテクチャでは、関数アドレスがオブジェクト アドレスよりも大きくなります。

C11、§ 6.3.2.3 ポインタ

へのポインターvoidは、任意のオブジェクト型へのポインターとの間で変換できます。任意のオブジェクト型へのポインターは、ポインターに変換したり void、元に戻すことができます。結果は元のポインタと等しくなります。

それ以外の場合は、一般的な拡張子です。

C11、§ J.5.7 関数ポインタのキャスト

オブジェクトへのポインターまたはへvoidのポインターは、関数へのポインターにキャストすることができ、データを関数として呼び出すことができます (6.5.4)。

あなたの例では、 を呼び出しませんfunc

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

pthread_t idThread;

void aFunction(void)
{
    while (1) {
        fprintf(stderr, "I've been called!\n");
        usleep(1000000);
    }
}

void *threadFunction(void *argFunc)
{
    void (*func)(void) = argFunc;
    func(); /* HERE */
}

int thread_creator(void (*f)(void))
{
    pthread_create(&idThread, NULL, threadFUnction, (void *) f);
}

int main(void)
{
    thread_creator(aFunction);
    while (1);
    return 0;
}
于 2012-09-12T16:41:15.077 に答える
-1

関数ポインターを含む疑わしいキャストは必要ありません。スレッドへの引数は、何でも含むことができる構造体へのポインターにすることができます。

#include <pthread.h>

struct arg {
    void (*func)(void);
    int other_stuff;
};

void function(void)
{

}

void *thread_function(void *arg)
{
    struct arg *a1 = arg;

    a1->func();

    return NULL;
}


int main(void)
{
    pthread_t tid;

    struct arg arg = {.func = function};

    pthread_create(&tid, NULL, thread_function, &arg);
    .
    .
    .

}
于 2012-09-12T16:50:33.143 に答える