编译期将C++成员函数映射为自由函数的实现方案
解决方案:预处理器宏模式匹配实现自动映射
针对你的需求,利用C++预处理器的模式匹配与宏参数拆分特性,可以直接实现STUB_FUNCTION(Apple::doThings)自动映射到&Apple_doThings_stub,以及CPP_METHOD_KEY(Apple::getV)转为FUNCTION_KEY(Apple_getV_stub),无需依赖模板或运行时映射表,完全适配C测试框架的函数指针哈希需求。
核心宏实现
1. 桩函数指针获取宏
通过预处理器的模式匹配,直接拆分Class::Func格式的成员函数名,拼接成对应的桩函数名称:
// 外层宏,对外暴露的调用接口 #define STUB_FUNCTION(member) _STUB_FUNCTION_IMPL(member) // 内层宏,匹配Class::Func格式,拆分类名和函数名并拼接桩函数后缀 #define _STUB_FUNCTION_IMPL(class_name::func_name) &class_name##_##func_name##_stub
调用示例:
// 自动获取&Apple_doThings_stub auto stub_ptr = STUB_FUNCTION(Apple::doThings);
2. 适配C测试框架的哈希宏
同理,实现CPP_METHOD_KEY到FUNCTION_KEY的自动转换:
// 假设C测试框架提供的哈希宏 #define FUNCTION_KEY(func) ((uintptr_t)&func) // 外层宏 #define CPP_METHOD_KEY(member) _CPP_METHOD_KEY_IMPL(member) // 内层宏,替换为桩函数的哈希调用 #define _CPP_METHOD_KEY_IMPL(class_name::func_name) FUNCTION_KEY(class_name##_##func_name##_stub)
调用示例:
// 等价于FUNCTION_KEY(Apple_getV_stub) auto key = CPP_METHOD_KEY(Apple::getV);
配套桩函数与桩类
你需要为每个C++成员函数生成对应的自由桩函数,再让桩类的成员函数调用这些桩函数:
// 对应Apple::doThings的自由桩函数 void Apple_doThings_stub() { // 桩逻辑:比如错误注入、返回预设值等 } // 桩类,继承原Apple类并覆盖成员函数 class AppleStub : public Apple { public: void doThings() override { Apple_doThings_stub(); } };
注意事项
- 兼容性:该宏实现支持GCC、Clang、MSVC等主流C++编译器,它们均支持预处理器的
::模式匹配。 - 重载处理:如果成员函数存在重载,需要扩展宏来区分不同重载版本,例如通过添加参数类型标识:
此时需要生成对应签名的桩函数// 处理重载的宏示例 #define STUB_FUNCTION_OVERLOADED(class_name, func_name, sig) &class_name##_##func_name##_##sig##_stub // 调用示例:对应Apple::doThings(int, float) auto stub_ptr = STUB_FUNCTION_OVERLOADED(Apple, doThings, int_float);Apple_doThings_int_float_stub。
内容的提问来源于stack exchange,提问作者Andrew
相关产品推荐
相关产品推荐

