如何在普通C中包装函数指针

如何在普通C中包装函数指针,c,lambda,function-pointers,createthread,C,Lambda,Function Pointers,Createthread,是否有可能以某种方式在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 i

是否有可能以某种方式在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; }

有没有其他方法可以避免执行此步骤?

没有,除了创建包装函数之外,没有其他方法。记住,它们也必须返回一个值。如果不包装(或忘记返回(虚拟)值),您将拥有UB。

不,除了创建包装函数之外,没有其他方法。记住,它们也必须返回一个值。如果您没有包装(或忘记返回(虚拟)值),您将有UB。

您可以创建包含函数类型、函数指针和参数(如果需要)的结构。线程函数必须检查函数类型,然后使用适当的签名调用函数,并传递存储在结构中的参数。您还可以创建用于创建这些结构的辅助函数,以简化编码。下面是两种可能的函数类型(带有void和int arg)的示例代码:

#包括
#包括
/*在结构中存储函数指针和参数所需的类型很少*/
typedef枚举FuncType
{
F_Void,
F_Int,
}功能类型;
类型定义无效(*VoidFuncPtr)(无效);
typedef void(*IntFuncPtr)(int);
typedef结构函数包装器
{
FuncType FuncType;
联盟
{
VoidFuncPtr voidFunc;
IntFuncPtr intFunc;
};
联盟
{
int intArg;
};
}功能包装;
/*线程函数,可以处理不同的函数*/
void ThreadFunc(void*arg)
{
FuncWrapper*wrapper=(FuncWrapper*)参数;
开关(包装器->功能类型)
{
案例F_无效:
包装器->voidFunc();
打破
案例F_Int:
包装器->intFunc(包装器->intArg);
打破
}
免费(包装纸);
}
/*用于创建FuncWrapper实例的助手函数*/
FuncWrapper*wrapVoidFunc(VoidFuncPtr func)
{
FuncWrapper*wrapper=(FuncWrapper*)malloc(sizeof(FuncWrapper));
包装->funcType=F_Void;
包装器->voidFunc=func;
返回包装器;
}
FuncWrapper*wrapIntFunc(IntFuncPtr func,int arg)
{
FuncWrapper*wrapper=(FuncWrapper*)malloc(sizeof(FuncWrapper));
包装器->funcType=F_Int;
包装器->intFunc=func;
包装器->intArg=arg;
返回包装器;
}
/*Dummy StartThread func,它只调用传入的函数*/
typedef void(*ThreadFuncPtr)(void*);
void StartThread(ThreadFuncPtr funcPtr,void*数据)
{
funcPtr(数据);
}
/*将被调用的函数*/
void myvoid函数(void)
{
printf(“调用myVoidFunction\n”);
}
void myIntFunction(int arg)
{
printf(“调用myIntFunction,arg=%d\n”,arg);
}
/*最后是主函数*/
int main()
{
StartThread(ThreadFunc,wrapVoidFunc(myVoidFunction));
StartThread(ThreadFunc,wrapIntFunc(myIntFunction,22));
返回0;
}

如果需要,您可以创建包含函数类型、函数指针和参数的结构。线程函数必须检查函数类型,然后使用适当的签名调用函数,并传递存储在结构中的参数。您还可以创建用于创建这些结构的辅助函数,以简化编码。下面是两种可能的函数类型(带有void和int arg)的示例代码:

#包括
#包括
/*在结构中存储函数指针和参数所需的类型很少*/
typedef枚举FuncType
{
F_Void,
F_Int,
}功能类型;
类型定义无效(*VoidFuncPtr)(无效);
typedef void(*IntFuncPtr)(int);
typedef结构函数包装器
{
FuncType FuncType;
联盟
{
VoidFuncPtr voidFunc;
IntFuncPtr intFunc;
};
联盟
{
int intArg;
};
}功能包装;
/*线程函数,可以处理不同的函数*/
void ThreadFunc(void*arg)
{
FuncWrapper*wrapper=(FuncWrapper*)参数;
开关(包装器->功能类型)
{
案例F_无效:
包装器->voidFunc();
打破
案例F_Int:
包装器->intFunc(包装器->intArg);
打破
}
免费(包装纸);
}
/*用于创建FuncWrapper实例的助手函数*/
FuncWrapper*wrapVoidFunc(VoidFuncPtr func)
{
FuncWrapper*wrapper=(FuncWrapper*)malloc(sizeof(FuncWrapper));
包装->funcType=F_Void;
包装器->voidFunc=func;
返回包装器;
}
FuncWrapper*wrapIntFunc(IntFuncPtr func,int arg)
{
FuncWrapper*wrapper=(FuncWrapper*)malloc(sizeof(FuncWrapper));
包装器->funcType=F_Int;
包装器->intFunc=func;
包装器->intArg=arg;
返回包装器;
}
/*Dummy StartThread func,它只调用传入的函数*/
typedef void(*ThreadFuncPtr)(void*);
void StartThread(ThreadFuncPtr funcPtr,void*数据)
{
funcPtr(数据);
}
/*将被调用的函数*/
void myvoid函数(void)
{
printf(“调用myVoidFunction\n”);
}
void myIntFunction(int arg)
{
printf(“调用myIntFunction,arg=%d\n”,arg);
}
/*最后是主函数*/
int main()
{
StartThread(ThreadFunc,wrapVoidFunc(myVoidFunction));
StartThread(ThreadFunc,wrapIntFunc(myIntFunction,22));
返回0;
}

你说得对,我刚刚注意到我忘了返回示例中的值+1您是对的,我刚刚注意到我忘记了返回示例中的值+1.
#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;
}