Clang 不支持 GCC 嵌套函数,但它支持Objective C 风格的“块”,即使在 C 模式下:
void f(void * d) {
void (^g)(void *) = ^(void * d){ };
g(d);
}
您需要使用以下命令调用它clang
命令而不是gcc
,并且还(?)通过-fblocks -lBlocksRuntime
给编译器。
您不能将块用作cleanup
直接值,因为它必须是一个函数名称,所以(窃取想法here)你需要添加一个间接层。定义一个函数来清理空块,并使您的 RAII 变量成为block您想要在范围末尾运行:
typedef void (^cleanup_block)(void);
static inline void do_cleanup(cleanup_block * b) { (*b)(); }
void do_stuff(const char *name) {
cleanup_block __attribute__((cleanup(do_cleanup))) __b = ^{ };
}
因为块形成闭包,所以您可以将操作放在变量上以直接在内部进行清理that堵塞...
void do_stuff(const char *name) {
struct mything * thing;
cleanup_block __attribute__((cleanup(do_cleanup))) __b = ^{ ao2_cleanup(thing); };
}
...并且应该像以前一样在范围末尾运行,由块上的清理调用。重新排列宏并添加__LINE__
所以它适用于多个声明:
#define CAT(A, B) CAT_(A, B)
#define CAT_(A, B) A##B
#define RAII_VAR(vartype, varname, initval, dtor) \
vartype varname = (initval); \
cleanup_block __attribute__((cleanup(do_cleanup))) CAT(__b_, __LINE__) = ^{ dtor(varname); };
void do_stuff(const char *name) {
RAII_VAR(struct mything *, thing, NULL, ao2_cleanup);
...
无论如何,类似的事情。