是否有可能以某种方式在C中“包装”一个函数指针,类似于你在C#中对lambda所做的那样?
我遇到的实际问题是:
我有几个不同参数的函数:
// more than two in actual code
void DoStuff(void) { ... }
void DoOtherStuff(int) { ... }
...我想创建几个线程来循环运行它们:
// 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 ++中我会使用lambda或指向调用另一个的方法的指针,但我不知道如何在C中执行此操作,除非我手动创建包装函数:
int CallDoStuff(void *dummy) { DoStuff(); return 0; }
int CallDoOtherStuff(void *dummy) { DoOtherStuff(42); return 0; }
还有其他方法可以避免这一步吗?
答案 0 :(得分:3)
不,除了创建包装函数之外别无他法。并记住他们也必须返回一个值。如果你没有包裹(或忘记返回(虚拟)值),你将拥有UB。
答案 1 :(得分: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;
}