无法将Emscripten编译的C++类导入Svelte组件求解决方案
解决方案
1. 修正Emscripten编译命令
原编译命令缺少关键的ES模块导出配置,且包含不必要的SDL依赖,替换为以下命令:
em++ -s ALLOW_MEMORY_GROWTH=1 -lembind -s ENVIRONMENT='web' -s SINGLE_FILE=1 -s MODULARIZE=1 -s EXPORT_ES6=1 -s EXPORT_NAME='createMyModule' chart.cpp -o glue.js
关键选项说明:
-s MODULARIZE=1:将编译产物封装为可导入的ES模块工厂函数-s EXPORT_ES6=1:生成符合ES6规范的模块代码,避免导出歧义-s EXPORT_NAME='createMyModule':指定模块工厂函数的名称,方便在Svelte中调用- 移除
-s USE_SDL=2:代码未使用SDL,减少不必要的依赖
2. 简化C++代码(可选)
移除代码中未使用的thread_local const val document定义,简化后的代码如下:
#include <emscripten/emscripten.h> #include <emscripten/val.h> #include <emscripten/bind.h> using namespace emscripten; using emscripten::val; using namespace std; class MyClass{ private : val canvas; val ctx; public : MyClass(std::string id){ canvas = val::global("document").call<val>("getElementById", val(id)); ctx = canvas.call<val>("getContext", val("2d") );} void greenRect(){ emscripten_run_script("alert('greenrect')"); ctx.set("fillStyle", "green"); ctx.call<void>("fillRect", 10, 10, 150, 100); } ~MyClass(){}}; EMSCRIPTEN_BINDINGS(MyClassModule) { class_<MyClass>("MyClass") .constructor<std::string>() .function("greenRect", &MyClass::greenRect) ;}
3. 调整Svelte组件代码
Emscripten生成的ES模块是异步加载的,需通过工厂函数初始化后再访问MyClass,同时确保页面中存在目标canvas元素:
<script> import { onMount } from "svelte"; import createMyModule from "../em/glue.js"; onMount(async () => { alert("pre"); // 异步初始化模块 const MyModule = await createMyModule(); // 实例化C++类 const chart = new MyModule.MyClass("canvas0"); alert("post"); chart.greenRect(); }); </script> <!-- 必须存在对应ID的canvas元素 --> <canvas id="canvas0" width="200" height="200"></canvas>
错误原因说明
- 原编译命令未启用ES模块配置,导致生成的代码不符合标准import规范,出现导出歧义错误
- Emscripten模块初始化是异步过程,未等待初始化完成就尝试实例化类会导致找不到构造函数
- 全局模式下的
Module.MyClass用法不适用于ES模块模式,需通过工厂函数返回的实例访问绑定的类
内容的提问来源于stack exchange,提问作者Dan
相关产品推荐
相关产品推荐

