You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:用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();
}

关键修改说明

  1. 扩展Foo类的回调接口:

    • 保留C风格函数指针类型CallbackFunction
    • 给SetCallback增加void* userData参数,用来传递Mock对象的地址(这是C风格回调常用的上下文传递方式)
    • 在InvokeCallback中调用回调时,把_userData传给回调函数
  2. 实现静态包装函数:

    • CallbackWrapper严格符合C风格回调的签名,接收void*类型参数
    • 函数内部将void*转换回MockFunction指针,调用其Call方法触发GMock的验证逻辑
  3. 测试用例调整:

    • 调用SetCallback时,传入包装函数CallbackWrapper和Mock对象的地址&callbackFunctionMock
    • 原有的EXPECT_CALL逻辑保持不变,依然可以验证回调的调用次数和参数

这个方案完全避开了std::function的使用,适配Arduino AVR的编译环境,同时能正常用GMock的断言机制验证回调行为。

内容的提问来源于stack exchange,提问作者uch.NZ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 19:14:55