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

C++用__event、__hook、__raise实现事件处理无输出及lambda处理问题

问题分析与修复

现有代码无输出的原因

__event、__hook、__raise是微软VC提供的专属非标准扩展,原生C场景下使用必须满足强制规则,当前代码缺失必要的事件源标记:

  • 事件源类必须添加[event_source(native)]属性,事件触发逻辑才能正常调度绑定的处理函数
  • 你提供的代码片段未引入<iostream>头文件,会导致std::cout无法正常输出(实际代码已引入可忽略该点)

基础可运行版本代码

#include <iostream>

[event_source(native)] // 原生C++事件源必须添加的标记
class C
{
public:
    __event void DoThing();
};

void handler()
{
    std::cout << "Handler" << std::endl;
}

int main()
{
    C c;
    __hook(&C::DoThing, &c, &handler);
    __raise c.DoThing(); // 触发后会正常输出Handler
    __unhook(&C::DoThing, &c, &handler); // 事件使用完后建议解绑避免异常
    return 0;
}

lambda作为事件处理函数的实现方法

无捕获lambda

无捕获lambda可以隐式转换为对应签名的函数指针,直接绑定即可:

#include <iostream>

[event_source(native)]
class C
{
public:
    __event void DoThing();
};

int main()
{
    C c;
    auto lambda_handler = []() {
        std::cout << "无捕获lambda触发成功" << std::endl;
    };
    __hook(&C::DoThing, &c, lambda_handler);
    __raise c.DoThing();
    __unhook(&C::DoThing, &c, lambda_handler);
    return 0;
}

有捕获lambda

有捕获的lambda无法直接转换为普通函数指针,需要通过代理层实现绑定:

#include <iostream>
#include <functional>

static std::function<void()> lambda_proxy;

[event_source(native)]
class C
{
public:
    __event void DoThing();
};

void proxy_func()
{
    if(lambda_proxy) lambda_proxy();
}

int main()
{
    C c;
    int test_val = 200;
    // 绑定带捕获的lambda
    lambda_proxy = [test_val]() {
        std::cout << "带捕获lambda触发成功,捕获值:" << test_val << std::endl;
    };
    __hook(&C::DoThing, &c, &proxy_func);
    __raise c.DoThing();
    __unhook(&C::DoThing, &c, &proxy_func);
    return 0;
}

注意:上述语法仅适配VC编译器,不属于C标准规范,跨平台场景不建议使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 00:48:01