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

Emscripten绑定raw pointer转std::shared_ptr非法错误如何解决?

报错根因

你遇到的BindingError: Passing raw pointer to smart pointer is illegal是因为IBar在绑定时指定了std::shared_ptr作为智能指针持有者类型,但implement方法默认返回的是原始指针类型的JS封装对象,Emscripten的类型校验不允许直接将原始指针对象传给要求智能指针的参数。

可行解决方案

方案1(最优,无额外适配成本)

修改IBar的绑定逻辑,给allow_subclass指定智能指针构造重载,让implement返回的对象默认被std::shared_ptr包裹:

EMSCRIPTEN_BINDINGS(IBar) {
    class_<IBar>("IBar")
        .smart_ptr<std::shared_ptr<IBar>>("IBar")
        .function("qux", &IBar::qux)
        // 新增第二个模板参数指定子类的智能指针类型
        .allow_subclass<BarWrapper, std::shared_ptr<BarWrapper>>("BarWrapper");
}

改完后,TS侧Module.Bar.implement返回的对象直接可以传入Foo.setBar,不需要额外转换。

方案2(新增转换工具函数)

如果不方便修改原有绑定逻辑,可以在C++侧新增一个原始指针转shared_ptr的工具函数,绑定后给JS侧调用:

// C++侧新增工具函数
std::shared_ptr<IBar> bar_to_shared(IBar* raw_ptr) {
    // 注意:如果原始指针已经被其他智能指针持有,要避免重复构造shared_ptr导致二次释放
    return std::shared_ptr<IBar>(raw_ptr);
}

// 新增绑定逻辑
EMSCRIPTEN_BINDINGS(BarUtils) {
    function("bar_to_shared", &bar_to_shared);
}

TS侧调用示例:

const bar = new Module.Bar.implement(new Bar())
const sharedBar = Module.bar_to_shared(bar)
foo.bar = sharedBar

方案3(修改Foo的setter绑定)

给Foo新增一个接受原始指针的setter重载,绑定的时候替换原有属性的setter:

class Foo {
    std::shared_ptr<IBar> getBar() const;
    void setBar(std::shared_ptr<IBar> bar);
    // 新增重载
    void setBarRaw(IBar* raw_bar) {
        setBar(std::shared_ptr<IBar>(raw_bar));
    }
};

// 修改Foo的绑定
EMSCRIPTEN_BINDINGS(Foo) {
    class_<Foo>("Foo")
        .constructor<>()
        .property("bar", &Foo::getBar, &Foo::setBarRaw);
}

改完后TS侧可以直接传原始指针给foo.bar。

注意事项
  • 所有涉及原始指针转shared_ptr的操作,都要确保原始指针没有被其他智能指针持有,避免引用计数混乱导致的内存泄漏或者野指针问题
  • JS侧持有Wasm对象的引用时,Wasm侧的引用计数不会自动减少,需要手动调用delete或者确保Wasm侧所有shared_ptr引用都被释放才会回收对象

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 10:36:03