jww*_*jww 5 c macros gcc clang gcc-extensions
我正在尝试解决第三方库中的问题.问题是库使用GCC嵌套在宏中的嵌套函数,而Clang不支持嵌套函数,并且没有计划这样做(参见,Clang Bug 6378 - 错误:函数上的非法存储类).
这是我和Clang痛点的宏观:
#define RAII_VAR(vartype, varname, initval, dtor) \
/* Prototype needed due to http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36774 */ \
auto void _dtor_ ## varname (vartype * v); \
void _dtor_ ## varname (vartype * v) { dtor(*v); } \
vartype varname __attribute__((cleanup(_dtor_ ## varname))) = (initval)
Run Code Online (Sandbox Code Playgroud)
以下是它的使用方法(来自代码注释):
* void do_stuff(const char *name)
* {
* RAII_VAR(struct mything *, thing, find_mything(name), ao2_cleanup);
* if (!thing) {
* return;
* }
* if (error) {
* return;
* }
* do_stuff_with_thing(thing);
* }
Run Code Online (Sandbox Code Playgroud)
所述锵用户Manua升状态中使用C++和lambda函数来模拟.我不确定这是最好的策略,而且C项目可能不会接受C++补丁(他们可能会首先考虑并且让我感到厌烦).
有没有办法重写宏,以便它(1)更适应Clang,(2)保留原始函数语义?
Clang不支持GCC嵌套函数,但它确实支持Objective C风格的"块",即使在C模式下:
void f(void * d) {
void (^g)(void *) = ^(void * d){ };
g(d);
}
Run Code Online (Sandbox Code Playgroud)
您需要使用clang
命令调用它而不是gcc
,并且(?)传递-fblocks -lBlocksRuntime
给编译器.
你不能直接使用块作为cleanup
值,因为它必须是一个函数名,所以(从这里窃取想法)你需要添加一个间接层.定义单个函数来清理void块,并使RAII'd变量成为您想要在作用域末尾运行的块:
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 = ^{ };
}
Run Code Online (Sandbox Code Playgroud)
因为块形成闭包,所以您可以将操作放在变量上以直接在该块内清理...
void do_stuff(const char *name) {
struct mything * thing;
cleanup_block __attribute__((cleanup(do_cleanup))) __b = ^{ ao2_cleanup(thing); };
}
Run Code Online (Sandbox Code Playgroud)
......并且应该像以前一样在范围的末尾运行,由块上的清理调用.重新排列宏并添加一个__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);
...
Run Code Online (Sandbox Code Playgroud)
无论如何,这样的事情.