C中的绑定变量?

C中的绑定变量?,c,macros,callback,C,Macros,Callback,我正在用C语言进行一个高度异步的项目。不幸的是,很快就会发现,有很多样板文件以指定包含回调用户数据的结构的形式出现 例如: typedef struct SomeUserData { int foo; int bar; } SomeUserData; void someCallback(void * userData) { SomeUserData * myData = userData; // ... free(myData); } void someFun

我正在用C语言进行一个高度异步的项目。不幸的是,很快就会发现,有很多样板文件以指定包含回调用户数据的结构的形式出现

例如:

typedef struct SomeUserData {
  int foo;
  int bar;
} SomeUserData;

void someCallback(void * userData)
{
    SomeUserData * myData = userData;
    // ...
    free(myData);
}

void someFunc(void)
{
    SomeUserData * myData = calloc(1, sizeof(*myData));
    myData->foo = 5;
    myData->bar = 10;
    doSomeAsync(someCallback, myData);
}
当只有一两个回调时,情况并没有那么糟糕,但是由于涉及到异步步骤的数量,我现在正在处理的项目部分有数百个回调


<> >我喜欢的是C++中的代码> BIN < /COD>。有没有一种方法可以在运行时使用可变参数实现一些C宏技巧或甚至某些东西的类似结果?

C宏技巧并不总是最容易调试的,但是:

#include <stdlib.h>

typedef struct Type1 {
    int foo ;
} Type1 ;
typedef struct Type2 {
    char* bar ;
} Type2 ;

#define CALLBACK( Type ) \
    void my##Type##Callback( Type* myData ) ; \
    void Type##Callback( void* userData ) \
    { \
        my##Type##Callback( (Type*) userData ) ; \
        free( userData ) ; \
    } \
    void my##Type##Callback( Type* myData )

CALLBACK( Type1 )
{
    printf( "Type1=%d\n", myData->foo ) ;
}

CALLBACK( Type2 )
{
    printf( "Type2=%s\n", myData->bar ) ;
}

void doAsync( void (*callback)( void* ), void* data )
{
    (*callback)( data ) ;
}

int main()
{
    Type1* t1 = calloc( 1, sizeof(*t1) ) ;
    Type2* t2 = calloc( 1, sizeof(*t2) ) ;
    t1->foo = 42 ;
    t2->bar = "TheAnswer" ;
    doAsync( myType1Callback, t1 ) ;
    doAsync( myType2Callback, t2 ) ;
}
#包括
类型定义结构类型1{
int foo;
}类型1;
类型定义结构类型2{
字符*条;
}类型2;
#定义回调(类型)\
作废我的##类型##回调(类型*myData)\
void类型##回调(void*userData)\
{ \
我的##类型##回调((Type*)用户数据)\
免费(用户数据)\
} \
作废我的##类型##回调(类型*myData)
回调(类型1)
{
printf(“Type1=%d\n”,myData->foo);
}
回调(类型2)
{
printf(“Type2=%s\n”,myData->bar);
}
void doAsync(void(*回调)(void*),void*数据)
{
(*回调)(数据);
}
int main()
{
Type1*t1=calloc(1,sizeof(*t1));
Type2*t2=calloc(1,sizeof(*t2));
t1->foo=42;
t2->bar=“TheAnswer”;
doAsync(myType1Callback,t1);
doAsync(myType2Callback,t2);
}

也许会有帮助。它声明了一个“myXXXCallback”,并使用指向指定类型的指针,然后创建一个“XXXCallback”,并使用void*调用特定类型的版本,然后释放数据。“技巧”是使用“##”操作符将传入的类型连接到函数名中。

我不这么认为。。。您可以通过让回调获取SomeuserData*并让doSomeAsync具有正确的签名来消除void*。这就是C++在引擎下通过模板所做的。如果有足够的一致性,这可能是考虑代码生成的好时机。使用python或其他工具处理单个输入文件(XML、CSV或其他格式),并生成所有适当的头文件和源文件,用于定义回调数据结构和函数原型。如果函数本身足够简单,您甚至可以生成它们。就要维护的重复代码而言,可以显著节省成本。