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

添加条件判断后QWebChannel实现JS调用C++功能失败

问题原因分析

核心问题是栈对象生命周期和异步逻辑不匹配,具体有两个错误点:

  • 你将QWebChannel channel、JsInterface jsInterface两个核心对象定义为if代码块内的栈变量,if块执行完成后,这两个对象会立即被栈内存回收。而QWebEngineView::loadFinished是异步信号,需要等网页加载完成后才会触发,触发时channel和jsInterface已经被销毁,你调用setWebChannel传入的指针成为野指针,通信链路直接失效。
  • 你在lambda捕获中用了[&browser]捕获指针的引用,browser本身是if块内的栈变量,if块结束后browser指针变量本身被销毁,lambda执行时访问的是野引用,也会导致逻辑异常。
修复方案

你可以任选以下任意一种方案修复:

方案1:提升变量作用域

将channel、jsInterface、browser的定义移到if块之外,保证对象生命周期覆盖异步信号的触发时机:

bool testwebchannel_main = true;
// 变量定义移到块外
QWebEngineView * browser = nullptr;
QWebChannel * channel = nullptr;
JsInterface * jsInterface = nullptr;

if ( testwebchannel_main )
{
    browser = new QWebEngineView;
    browser->resize(QSize(800,600));
    browser->show();
    browser->load(QUrl("http://www.wikipedia.org"));

    channel = new QWebChannel;
    jsInterface = new JsInterface;
    browser->page()->setWebChannel(channel, 42);
    channel->registerObject(QString("JsInterface"), jsInterface);
    // 捕获改为值捕获,直接存指针地址
    QObject::connect(browser, &QWebEngineView::loadFinished, [browser](bool ok)
    {
        qDebug()<<"Load Finished " << ok;

        // TEST CODE HERE
        QString code = QStringLiteral(
        R"DELIM(

        var links = document.getElementsByTagName('a');
        for ( var i=0; i<links.length; ++i)
        {
            links[i].style.backgroundColor = 'yellow';
        };

        )DELIM");
        browser->page()->runJavaScript(code, 42);

        browser->page()->runJavaScript(qWebChannelJs(), 42);

        QString code2 = QStringLiteral(
        R"DELIM(
        window.webChannel = new QWebChannel(qt.webChannelTransport, function( channel)
        {
            var cpp = channel.objects.JsInterface;
            cpp.log("Hello from JavaScript");
        });

        )DELIM");
        browser->page()->runJavaScript(code2, 42);
    });
}

方案2:绑定对象生命周期到QWebEngineView

利用Qt的父子内存管理机制,将channel和jsInterface的父对象设为browser,browser销毁时会自动回收子对象,同时捕获改为值捕获:

bool testwebchannel_main = true;

if ( testwebchannel_main )
{
    QWebEngineView * browser = new QWebEngineView;
    browser->resize(QSize(800,600));
    browser->show();
    browser->load(QUrl("http://www.wikipedia.org"));

    // 动态分配,设置父对象为browser
    QWebChannel * channel = new QWebChannel(browser);
    JsInterface * jsInterface = new JsInterface(browser);
    browser->page()->setWebChannel(channel, 42);
    channel->registerObject(QString("JsInterface"), jsInterface);
    // 值捕获browser指针
    QObject::connect(browser, &QWebEngineView::loadFinished, [browser](bool ok)
    {
        qDebug()<<"Load Finished " << ok;

        // 原有逻辑不变
        QString code = QStringLiteral(
        R"DELIM(

        var links = document.getElementsByTagName('a');
        for ( var i=0; i<links.length; ++i)
        {
            links[i].style.backgroundColor = 'yellow';
        };

        )DELIM");
        browser->page()->runJavaScript(code, 42);

        browser->page()->runJavaScript(qWebChannelJs(), 42);

        QString code2 = QStringLiteral(
        R"DELIM(
        window.webChannel = new QWebChannel(qt.webChannelTransport, function( channel)
        {
            var cpp = channel.objects.JsInterface;
            cpp.log("Hello from JavaScript");
        });

        )DELIM");
        browser->page()->runJavaScript(code2, 42);
    });
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.15 07:54:02