如何仅用C预处理器提取头文件函数名至boost.preprocessor结构
纯C预处理器提取被宏包裹的函数名至Boost.Preprocessor兼容结构
核心思路
针对FOO [返回类型] BAR 函数名(参数);的固定格式,利用C预处理器的参数拆分特性,剥离FOO和BAR标记,提取函数名,再将收集到的函数名组织成Boost.Preprocessor支持的序列/元组格式。
步骤1:单个函数名提取宏
定义宏拆分函数声明,精准提取函数名:
// 拆解函数声明,提取函数名 #define EXTRACT_SINGLE_FUNC(decl) _EXTRACT_HELPER(decl) #define _EXTRACT_HELPER(foo, ret_type, bar, func_name, ...) func_name // 测试示例 #define TEST_F1 EXTRACT_SINGLE_FUNC(FOO int * BAR f(long, double)) #define TEST_F2 EXTRACT_SINGLE_FUNC(FOO void BAR g()) // TEST_F1 展开为 f,TEST_F2 展开为 g
步骤2:组织成Boost.Preprocessor兼容结构
生成逗号分隔序列(如(f, g))
通过宏收集函数名,生成符合Boost.Preprocessor序列要求的格式:
// 定义序列构建宏 #define SEQ_START() #define SEQ_ADD(seq, func) seq, func #define SEQ_FINALIZE(seq) (seq) // 构建函数名序列 #define MY_FUNC_SEQ \ SEQ_FINALIZE( \ SEQ_ADD( \ SEQ_ADD(SEQ_START(), EXTRACT_SINGLE_FUNC(FOO int * BAR f(long, double))), \ EXTRACT_SINGLE_FUNC(FOO void BAR g()) \ ) \ ) // MY_FUNC_SEQ 最终展开为 (f, g)
生成嵌套元组(如(f)(g))
如果需要这种格式,调整构建宏即可:
#define TUPLE_START() #define TUPLE_ADD(tuple, func) tuple(func) #define TUPLE_FINALIZE(tuple) tuple #define MY_FUNC_TUPLES \ TUPLE_FINALIZE( \ TUPLE_ADD( \ TUPLE_ADD(TUPLE_START(), EXTRACT_SINGLE_FUNC(FOO int * BAR f(long, double))), \ EXTRACT_SINGLE_FUNC(FOO void BAR g()) \ ) \ ) // MY_FUNC_TUPLES 最终展开为 (f)(g)
步骤3:函数名转字符串字面量
结合Boost.Preprocessor迭代,将序列中的函数名转为字符串:
#include <boost/preprocessor/seq/for_each.hpp> // 字符串化宏 #define STRINGIFY(x) #x #define FUNC_TO_STR(func) STRINGIFY(func) // 迭代处理序列中的每个函数名 #define PRINT_FUNC(r, _, func) puts(FUNC_TO_STR(func)); // 调用迭代 BOOST_PP_SEQ_FOR_EACH(PRINT_FUNC, _, MY_FUNC_SEQ)
注意事项
- 若原头文件包含大量函数声明,手动枚举较繁琐,但纯C预处理器无法自动过滤非函数声明(如枚举、结构体),需手动筛选目标函数声明传入宏。
- 确保
FOO和BAR未被其他代码重定义,若有冲突可临时重命名标记宏后再处理。
内容的提问来源于stack exchange,提问作者SuibianP
相关产品推荐
相关产品推荐

