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

如何在Google Test中使用C语言回调注册函数?

问题描述

我有一个包含回调函数及其注册函数的C语言文件,需要通过Google Test(GTest)对其进行测试。当前尝试使用静态回调函数,但无法访问测试夹具中的m_value成员变量,希望通过回调将m_value赋值为3,示例代码及测试失败结果如下:

#include <gtest/gtest.h>

/////////////////////////////////////////
// 这段代码在C文件中
/////////////////////////////////////////
void (*add)(int a, int b);

void RegisterAddCallback(void (*callback)(int a, int b))
{
    add = callback;
}
/////////////////////////////////////////

// 我目前的尝试方式
// static int s_value;
// static void add_static_callback(int a, int b)
// {
//     s_value = a + b;
// }

class CallbackTests : public ::testing::Test
{
public:
    int m_value;
    void SetUp() override
    {
        m_value = 0;
    }   

    static void add_static_callback(int a, int b)
    {
        // 这里无法访问m_value,但我需要修改它
        int value = a + b;
    }
};

TEST_F(CallbackTests, StaticCallback)
{
    RegisterAddCallback(add_static_callback);
    add(1, 2);
    EXPECT_EQ(m_value, 3);
}

测试失败结果:

Expected equality of these values:
  m_value
    Which is: 0
  3
[  FAILED  ] CallbackTests.StaticCallback (0 ms)
可行实现方法

方法1:全局指针指向当前测试实例(单线程测试适用)

利用全局指针关联当前测试实例,让静态回调通过指针访问非静态成员m_value:

#include <gtest/gtest.h>

/////////////////////////////////////////
// 原C文件代码
/////////////////////////////////////////
void (*add)(int a, int b);

void RegisterAddCallback(void (*callback)(int a, int b))
{
    add = callback;
}
/////////////////////////////////////////

static CallbackTests* g_current_test = nullptr;

class CallbackTests : public ::testing::Test
{
public:
    int m_value;
    void SetUp() override
    {
        m_value = 0;
        g_current_test = this;
    }

    void TearDown() override
    {
        g_current_test = nullptr;
    }

    static void add_static_callback(int a, int b)
    {
        if (g_current_test != nullptr)
        {
            g_current_test->m_value = a + b;
        }
    }
};

TEST_F(CallbackTests, StaticCallback)
{
    RegisterAddCallback(add_static_callback);
    add(1, 2);
    EXPECT_EQ(m_value, 3);
}

方法2:线程局部存储(多线程并行测试适用)

将全局指针改为线程局部变量,避免多线程测试时的实例冲突:

#include <gtest/gtest.h>

/////////////////////////////////////////
// 原C文件代码
/////////////////////////////////////////
void (*add)(int a, int b);

void RegisterAddCallback(void (*callback)(int a, int b))
{
    add = callback;
}
/////////////////////////////////////////

static thread_local CallbackTests* g_current_test = nullptr;

class CallbackTests : public ::testing::Test
{
public:
    int m_value;
    void SetUp() override
    {
        m_value = 0;
        g_current_test = this;
    }

    void TearDown() override
    {
        g_current_test = nullptr;
    }

    static void add_static_callback(int a, int b)
    {
        if (g_current_test != nullptr)
        {
            g_current_test->m_value = a + b;
        }
    }
};

TEST_F(CallbackTests, StaticCallback)
{
    RegisterAddCallback(add_static_callback);
    add(1, 2);
    EXPECT_EQ(m_value, 3);
}

方法3:修改C代码的回调签名(最优解)

如果允许修改原C代码,给回调添加用户数据参数,彻底摆脱全局变量依赖:

修改后的C代码:

#include <stddef.h>

typedef void (*add_callback_t)(int a, int b, void* user_data);

static add_callback_t add = nullptr;
static void* add_user_data = nullptr;

void RegisterAddCallback(add_callback_t callback, void* user_data)
{
    add = callback;
    add_user_data = user_data;
}

void CallAdd(int a, int b)
{
    if (add != nullptr)
    {
        add(a, b, add_user_data);
    }
}

对应的GTest代码:

#include <gtest/gtest.h>

typedef void (*add_callback_t)(int a, int b, void* user_data);
void RegisterAddCallback(add_callback_t callback, void* user_data);
void CallAdd(int a, int b);

class CallbackTests : public ::testing::Test
{
public:
    int m_value;
    void SetUp() override
    {
        m_value = 0;
    }

    static void add_callback(int a, int b, void* user_data)
    {
        CallbackTests* test = static_cast<CallbackTests*>(user_data);
        test->m_value = a + b;
    }
};

TEST_F(CallbackTests, CallbackWithUserData)
{
    RegisterAddCallback(CallbackTests::add_callback, this);
    CallAdd(1, 2);
    EXPECT_EQ(m_value, 3);
}

内容的提问来源于stack exchange,提问作者Youngmin Kim

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 13:16:14