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

如何编写TEdgeBrowser ExecuteScript执行后的Lambda函数及相关疑问

关于TEdgeBrowser调用ExecuteScript及Lambda回调的问题

问题描述

我使用TEdgeBrowser组件,通过DefaultInterface调用ExecuteScript方法,代码框架如下:

EdgeBrowser1->DefaultInterface->ExecuteScript()

该方法需要传入两个参数:System::WideChar * javaScript 和 const _di_ICoreWebView2ExecuteScriptCompletedHandler handler。

我想用clang编译器写一个Lambda函数作为回调,执行完成后自动销毁,尝试了以下代码:

EdgeBrowser1->DefaultInterface->ExecuteScript(L"alert('Hello World!')",
    _di_ICoreWebView2ExecuteScriptCompletedHandler(
        new TCppInterfacedObject<TCoreWebView2ExecuteScriptCompletedHandler>(
            [](HRESULT errorCode, PCWSTR resultObjectAsJson) -> HRESULT {
                if (FAILED(errorCode))
                {
                    ShowMessage("Failed to execute script");
                    return errorCode;
                }
                ShowMessage("Script executed successfully");
                return S_OK;
            })));

但发现TCoreWebView2ExecuteScriptCompletedHandler未定义,请问该如何修改才能正常运行?

另外还有三个疑问:

  1. 在WebView2.hpp中,Invoke方法的第二个参数定义为System::WideChar *,用LPCWSTR会提示虚方法Invoke未实现,必须添加__stdcall,我已经修正为:
HRESULT __stdcall Invoke(HRESULT errorCode, System::WideChar* resultObjectAsJson)

这样处理是否正确?
2. 根据TCppInterfacedObject的文档,它已经实现了QueryInterface、AddRef、Release等IUnknown方法,那还需要使用INTFOBJECT_IMPL_IUNKNOWN宏吗?注释掉这个宏后没有出现方法未实现的警告,但手动实现ICoreWebView2ExecuteScriptCompletedHandler时会出现警告。
3. 在返回S_OK前需要调用Release()吗?已知存在引用计数机制,ExecuteScript会处理引用计数吗?我希望这个Lambda或ICoreWebView2ExecuteScriptCompletedHandler实例执行后不再占用内存。


核心问题解决:TCoreWebView2ExecuteScriptCompletedHandler未定义的处理

你需要自行实现一个继承自ICoreWebView2ExecuteScriptCompletedHandler的适配类,用来桥接Lambda和WebView2的回调接口。以下是两种可行的写法:

写法一:自定义回调处理类

// 继承TCppInterfacedObject,自动获得IUnknown的实现
class TCoreWebView2ExecuteScriptHandler : public TCppInterfacedObject<ICoreWebView2ExecuteScriptCompletedHandler>
{
public:
    using TCallback = std::function<HRESULT(HRESULT, PCWSTR)>;
    TCallback FCallback;

    explicit TCoreWebView2ExecuteScriptHandler(TCallback&& Callback) : FCallback(std::move(Callback)) {}

    // 严格匹配接口定义的Invoke方法签名
    HRESULT __stdcall Invoke(HRESULT errorCode, System::WideChar* resultObjectAsJson) override
    {
        if (FCallback)
        {
            return FCallback(errorCode, resultObjectAsJson);
        }
        return E_FAIL;
    }
};

// 调用ExecuteScript的代码
EdgeBrowser1->DefaultInterface->ExecuteScript(L"alert('Hello World!')",
    _di_ICoreWebView2ExecuteScriptCompletedHandler(
        new TCoreWebView2ExecuteScriptHandler(
            [](HRESULT errorCode, PCWSTR resultObjectAsJson) -> HRESULT {
                if (FAILED(errorCode))
                {
                    ShowMessage("Failed to execute script");
                    return errorCode;
                }
                ShowMessage("Script executed successfully");
                return S_OK;
            })));

写法二:直接适配Lambda到接口

利用TCppInterfacedObject的Lambda适配能力,直接实现接口的Invoke方法:

EdgeBrowser1->DefaultInterface->ExecuteScript(L"alert('Hello World!')",
    _di_ICoreWebView2ExecuteScriptCompletedHandler(
        new TCppInterfacedObject<ICoreWebView2ExecuteScriptCompletedHandler>(
            // 定义Lambda回调逻辑
            [](HRESULT errorCode, System::WideChar* result) -> HRESULT {
                if (FAILED(errorCode))
                {
                    ShowMessage("Failed to execute script");
                    return errorCode;
                }
                ShowMessage("Script executed successfully");
                return S_OK;
            },
            // 桥接接口Invoke方法到Lambda
            [](ICoreWebView2ExecuteScriptCompletedHandler* iface, HRESULT errorCode, System::WideChar* result) -> HRESULT {
                auto lambdaHolder = static_cast<TCppInterfacedObject<ICoreWebView2ExecuteScriptCompletedHandler>*>(iface);
                auto callback = lambdaHolder->GetLambda();
                return callback(errorCode, result);
            })));

关键注意点:必须保证Invoke方法的参数类型、顺序和调用约定(__stdcall)完全匹配ICoreWebView2ExecuteScriptCompletedHandler的定义。


疑问解答

  1. 关于Invoke方法的修正
    你的修正完全正确。WebView2.hpp中定义的Invoke方法签名是固定的,必须严格匹配HRESULT __stdcall Invoke(HRESULT, System::WideChar*),否则编译器会判定你未实现接口的纯虚函数,导致编译失败。

  2. 是否需要INTFOBJECT_IMPL_IUNKNOWN宏
    不需要。TCppInterfacedObject已经内置了IUnknown核心方法(QueryInterface、AddRef、Release)的实现,继承它就无需再使用该宏。而手动实现ICoreWebView2ExecuteScriptCompletedHandler时,因为没有继承TCppInterfacedObject,必须通过INTFOBJECT_IMPL_IUNKNOWN宏生成IUnknown的实现,否则会出现方法未实现的警告。

  3. 是否需要手动调用Release()
    不需要手动调用。ExecuteScript方法会在回调执行完成后自动调用Release(),TCppInterfacedObject的引用计数机制会在计数降为0时自动销毁对象。整个生命周期由WebView2的内部逻辑管理,不会造成内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 04:55:03