2016-06-17 5 views
0

関数ポインタをCでラップすることは可能ですか?C#でラムダを使用する場合と同様です。私が午前関数ポインタをCでラップする方法

実際の問題は、次のとおりです。

私は異なるパラメータを持つ関数のカップルを持っている:

// more than two in actual code 
void DoStuff(void) { ... } 
void DoOtherStuff(int) { ... } 

...と私はループ内でこれらを実行するスレッドのカップルを作成したいです:C#の/ Cで

// this won't work because it expects a LPTHREAD_START_ROUTINE, 
// which is int(*fn)(void*) 
tHnd1 = CreateThread(NULL, 0, &DoStuff, NULL, 0, &tId); 
tHnd2 = CreateThread(NULL, 0, &DoOtherStuff, NULL, 0, &tId); 

++私は、ラムダ、または他のものを呼ぶだろうメソッドへのポインタを使用しますが、私は手動でラッパー関数を作成しない限り、Cでこれを行う方法を見当もつかない。

int CallDoStuff(void *dummy) { DoStuff(); return 0; } 
int CallDoOtherStuff(void *dummy) { DoOtherStuff(42); return 0; } 

この手順を実行する他の方法はありますか?

+3

いいえ、本当にありません。 – melpomene

答えて

1

必要に応じて、関数タイプ、関数ポインタ、および引数を含む構造体を作成できます。スレッド関数は、関数の型をチェックし、適切なシグネチャを使用して関数を呼び出し、構造体に格納されたパラメータを渡す必要があります。これらの構造を作成するために使用されるヘルパー関数を作成して、コーディングを簡略化することもできます。以下は、2つの可能な関数型(voidとint argを持つ)のコード例です:

#include <stdio.h> 
#include <stdlib.h> 

/* Few types needed to store function pointer and arguments in struct */ 
typedef enum FuncType 
{ 
    F_Void, 
    F_Int, 
} FuncType; 

typedef void(*VoidFuncPtr)(void); 
typedef void(*IntFuncPtr)(int); 

typedef struct FuncWrapper 
{ 
    FuncType funcType; 
    union 
    { 
     VoidFuncPtr voidFunc; 
     IntFuncPtr intFunc; 
    }; 
    union 
    { 
     int intArg; 
    }; 
} FuncWrapper; 

/* Thread func which can handle different functions */ 
void ThreadFunc(void* arg) 
{ 
    FuncWrapper* wrapper = (FuncWrapper*)arg; 
    switch (wrapper->funcType) 
    { 
    case F_Void: 
     wrapper->voidFunc(); 
     break; 
    case F_Int: 
     wrapper->intFunc(wrapper->intArg); 
     break; 
    } 
    free(wrapper); 
} 

/* Helper functions used to create FuncWrapper instances */ 
FuncWrapper* wrapVoidFunc(VoidFuncPtr func) 
{ 
    FuncWrapper* wrapper = (FuncWrapper*)malloc(sizeof(FuncWrapper)); 
    wrapper->funcType = F_Void; 
    wrapper->voidFunc = func; 
    return wrapper; 
} 

FuncWrapper* wrapIntFunc(IntFuncPtr func, int arg) 
{ 
    FuncWrapper* wrapper = (FuncWrapper*)malloc(sizeof(FuncWrapper)); 
    wrapper->funcType = F_Int; 
    wrapper->intFunc = func; 
    wrapper->intArg = arg; 
    return wrapper; 
} 

/* Dummy StartThread func, which simply calls passed in function */ 
typedef void(*ThreadFuncPtr)(void*); 
void StartThread(ThreadFuncPtr funcPtr, void* data) 
{ 
    funcPtr(data); 
} 

/* Functions which will be called */ 
void myVoidFunction(void) 
{ 
    printf("myVoidFunction called\n"); 
} 

void myIntFunction(int arg) 
{ 
    printf("myIntFunction called, arg = %d\n", arg); 
} 

/* Finally the main func */ 
int main() 
{ 
    StartThread(ThreadFunc, wrapVoidFunc(myVoidFunction)); 
    StartThread(ThreadFunc, wrapIntFunc(myIntFunction, 22)); 
    return 0; 
} 
3

いいえ、実際にはラッパー関数を作成する以外の方法はありません。彼らは価値を返さなければならないことを忘れないでください。ラップしない場合(または(ダミー)値を返すことを忘れた場合)、あなたはUBになります。

+0

あなたが正しいです、私は例で値を返すのを忘れていたことに気付きました。 +1 – Lou

関連する問題