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
相关产品推荐
相关产品推荐

