2016-06-17 3 views
0

C에서 함수 포인터를 C로 래핑하는 것이 가능합니까? C#에서 람다를 사용하는 것과 비슷합니다. 나는 데함수 포인터를 일반 C로 래핑하는 방법

실제 문제는 다음과 같습니다

내가 다른 매개 변수 기능의 몇 가지 있습니다

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

을 ... 그리고 루프에서 다음을 실행하는 스레드의 몇 가지를 만들려면 :

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++는 내가 람다, 또는 다른 하나를 호출 할 방법에 대한 포인터를 사용합니다,하지만 난 어떻게 수동으로 래퍼 함수를 ​​작성하지 않는 한, C에서이 작업을 수행하는 단서가 없다 :

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

이 단계를 수행하지 않으려면 다른 방법이 있습니까?

+3

아니요. – melpomene

답변

1

함수 유형, 함수 포인터 및 필요한 경우 인수가 포함될 구조를 만들 수 있습니다. 스레드 함수는 함수 형식을 확인한 다음 적절한 서명을 사용하여 함수를 호출하고 구조체에 저장된 매개 변수를 전달해야합니다. 이러한 구조를 만드는 데 사용되는 도우미 함수를 만들어 코딩을 단순화 할 수도 있습니다. 다음은 가능한 두 가지 함수 유형 (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