set_target_properties(ModuleOpenDrive PROPERTIES LINK_FLAGS "\\
–bind \\
-s ENVIRONMENT=web \\
-s MODULARIZE=1 \\
-s EXPORT_NAME='\\"libOpenDrive\\"' \\
-s EXPORTED_RUNTIME_METHODS='[\\"cwrap\\"]' \\
-s FORCE_FILESYSTEM=1 \\
-s ALLOW_MEMORY_GROWTH=1 \\
")
明白了!我们将通过一个完整的示例,来演示每个 Emscripten 参数的作用,并且分别展示加上和去掉这些参数后的影响。
示例项目结构
wasm-demo/
├── src/
│ └── main.cpp
├── CMakeLists.txt
└── index.html
1. src/main.cpp(C++ 源码)
#include <emscripten/bind.h>
#include <iostream>
#include <string>
using namespace emscripten;
// 示例类:用于 Embind 测试
class Greeter {
public:
Greeter(const std::string& name) : name(name) {}
std::string greet() const { return "Hello, " + name; }
private:
std::string name;
};
// 示例函数:用于 cwrap 测试
extern "C" {
int add(int a, int b) {
return a + b;
}
const char* sayHello(const char* name) {
static std::string result;
result = "Hello from C++: " + std::string(name);
return result.c_str();
}
}
// 使用 Embind 导出类和方法
EMSCRIPTEN_BINDINGS(my_module) {
class_<Greeter>("Greeter")
.constructor<std::string>()
.function("greet", &Greeter::greet);
}
2. CMakeLists.txt
cmake_minimum_required(VERSION 3.13.4)
project(ModuleOpenDrive)
add_executable(ModuleOpenDrive
src/main.cpp
)
# 设置编译器为 Emscripten
set(CMAKE_CXX_COMPILER_WORKS TRUE)
set(CMAKE_C_COMPILER_WORKS TRUE)
# 默认配置,不加任何额外参数
# set_target_properties(ModuleOpenDrive PROPERTIES LINK_FLAGS "\\
# –bind \\
# -s ENVIRONMENT=web \\
# -s MODULARIZE=1 \\
# -s EXPORT_NAME='\\"libOpenDrive\\"' \\
# -s EXPORTED_RUNTIME_METHODS='[\\"cwrap\\"]' \\
# -s FORCE_FILESYSTEM=1 \\
# -s ALLOW_MEMORY_GROWTH=1 \\
# ")
set_target_properties(ModuleOpenDrive PROPERTIES SUFFIX ".js")
3. index.html(JS 调用示例)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Emscripten Demo</title>
</head>
<body>
<h1>WebAssembly Demo</h1>
<script src="ModuleOpenDrive.js"></script>
<script>
// 注意:这里假设没有使用 MODULARIZE 和 EXPORT_NAME 参数
Module.onRuntimeInitialized = function() {
console.log('Module loaded');
// 使用 Embind 类
let greeter = new Module.Greeter("World");
console.log(greeter.greet()); // 输出: Hello, World
// 使用 cwrap 封装函数
const sayHello = Module.cwrap('sayHello', 'string', ['string']);
console.log(sayHello("Alice")); // 输出: Hello from C++: Alice
// 直接调用 _ 函数
console.log(Module._add(2, 3)); // 输出: 5
};
</script>
</body>
</html>
逐个参数说明与 demo
1. –bind
含义:
启用 Embind 功能,允许将 C++ 类导出给 JavaScript。
加上之后:
- 在 C++ 中使用 EMSCRIPTEN_BINDINGS 定义要导出的类。
- 在 JS 中可以通过 new Module.Greeter() 创建对象。
去掉之后:
- Module.Greeter 不会被定义,导致在 JS 中无法创建对象。
- 错误提示:Module.Greeter is undefined.
C++ 示例:
EMSCRIPTEN_BINDINGS(my_module) {
class_<Greeter>("Greeter")
.constructor<std::string>()
.function("greet", &Greeter::greet);
}
JS 示例:
let greeter = new Module.Greeter("World");
console.log(greeter.greet());
2. -s ENVIRONMENT=web
含义:
指定模块运行环境为浏览器。
加上之后:
- 确保生成的 .js 文件适用于浏览器环境。
- 避免 Node.js 特定行为影响浏览器兼容性。
去掉之后:
- 可能会导致在浏览器中加载时出现问题,特别是如果依赖于特定的浏览器特性或行为。
JS 示例: 无需修改代码,仅确保在 HTML 文件中正确引用 .js 文件即可。
3. -s MODULARIZE=1
含义:
将模块封装为可调用工厂函数,返回 Promise。
加上之后:
- 模块需要通过 libOpenDrive().then(…) 来加载。
- 更适合现代 JS 应用开发。
去掉之后:
- 模块直接作为全局变量 Module 存在,需等待 Module.onRuntimeInitialized 触发。
JS 示例:
libOpenDrive().then(Module => {
let greeter = new Module.Greeter("World");
console.log(greeter.greet());
});
4. -s EXPORT_NAME='\\"libOpenDrive\\"'
含义:
设置模块加载后的全局变量名。
加上之后:
- 模块通过 libOpenDrive() 加载。
- 提供更具语义化的模块名称。
去掉之后:
- 默认模块名为 Module,可能会与其他模块冲突。
JS 示例:
libOpenDrive().then(Module => {
let greeter = new Module.Greeter("World");
console.log(greeter.greet());
});
5. -s EXPORTED_RUNTIME_METHODS='[\\"cwrap\\"]'
含义:
启用某些运行时工具函数,如 cwrap。
加上之后:
- 可以使用 Module.cwrap 包装 C 函数,便于在 JS 中调用。
去掉之后:
- Module.cwrap 未定义,无法使用该功能。
JS 示例:
const sayHello = Module.cwrap('sayHello', 'string', ['string']);
console.log(sayHello("Alice"));
6. -s FORCE_FILESYSTEM=1
含义:
强制启用虚拟文件系统。
加上之后:
- 可以使用 FS_createDataFile 等文件系统 API。
去掉之后:
- 文件系统相关操作可能失败。
JS 示例:
Module.FS_createDataFile(".", "hello.txt", "This is a test file.", true, true);
console.log(Module.FS.readFile("/hello.txt", { encoding: 'utf8' }));
7. -s ALLOW_MEMORY_GROWTH=1
含义:
允许 WASM 内存动态增长。
加上之后:
- 可以分配超过默认限制的内存。
去掉之后:
- 分配过大内存可能导致崩溃。
C++ 示例:
void* ptr = malloc(1024 * 1024 * 20); // 分配 20MB
free(ptr);
JS 示例:
let ptr = Module._malloc(1024 * 1024 * 20);
Module._free(ptr);
以上就是针对每个参数的详细说明及其对应的使用示例。你可以根据需求选择合适的参数组合来构建你的 WebAssembly 模块。
评论前必须登录!
注册