求助:用GoogleTest/GMock测试C风格回调函数编译报错
解决GoogleTest/GMock测试C风格回调的方案
针对你在Arduino AVR平台无法使用std::function,需要测试C风格回调的问题,可以通过静态包装函数桥接GMock的Mock对象和C风格函数指针,具体实现如下:
修改后的完整代码
#include <gtest/gtest.h> #include <gmock/gmock.h> using ::testing::_; using ::testing::MockFunction; class Foo { public: typedef void (*CallbackFunction)(void *); // 改用C风格回调类型 void SetCallback(CallbackFunction callback, void* userData = nullptr) { _callback = callback; _userData = userData; } void InvokeCallback() { if (_callback != nullptr) { _callback(_userData); } } private: CallbackFunction _callback = nullptr; void* _userData = nullptr; }; // 静态包装函数:适配C风格回调签名,调用Mock对象的方法 static void CallbackWrapper(void* mockPtr) { if (mockPtr != nullptr) { auto* mock = static_cast<MockFunction<void(void*)>*>(mockPtr); mock->Call(nullptr); } } class FooTest : public testing::Test { public: MockFunction<void(void*)> callbackFunctionMock; }; TEST_F(FooTest, simple) { EXPECT_CALL(callbackFunctionMock, Call(_)).Times(1); Foo foo; // 传入包装函数和Mock对象的地址 foo.SetCallback(CallbackWrapper, &callbackFunctionMock); foo.InvokeCallback(); }
关键修改说明
扩展Foo类的回调接口:
- 保留C风格函数指针类型
CallbackFunction - 给
SetCallback增加void* userData参数,用来传递Mock对象的地址(这是C风格回调常用的上下文传递方式) - 在
InvokeCallback中调用回调时,把_userData传给回调函数
- 保留C风格函数指针类型
实现静态包装函数:
CallbackWrapper严格符合C风格回调的签名,接收void*类型参数- 函数内部将
void*转换回MockFunction指针,调用其Call方法触发GMock的验证逻辑
测试用例调整:
- 调用
SetCallback时,传入包装函数CallbackWrapper和Mock对象的地址&callbackFunctionMock - 原有的
EXPECT_CALL逻辑保持不变,依然可以验证回调的调用次数和参数
- 调用
这个方案完全避开了std::function的使用,适配Arduino AVR的编译环境,同时能正常用GMock的断言机制验证回调行为。
内容的提问来源于stack exchange,提问作者uch.NZ
相关产品推荐
相关产品推荐

