如何通过Clang使用WebAssembly Reference Types实现externref交互
Clang + LLD 开发C语言WebAssembly应用的externref相关问题解答
所有相关操作都需要在编译、链接阶段开启reference types支持,编译/链接参数添加-mreference-types。
1. 编写以externref为参数的C函数
Clang针对Wasm平台提供了内置的__externref_t类型,直接对应Wasm标准的externref不透明引用类型,直接将其作为函数参数类型即可。如果需要将函数导出给JavaScript调用,额外添加export_name属性指定导出名称。
示例代码:
#include <stdint.h> // 导出名为process_js_ref的Wasm函数,接收externref参数,返回uint32_t类型结果 __attribute__((export_name("process_js_ref"))) uint32_t process_js_ref(__externref_t js_value) { // C侧无法直接操作externref的内容,仅可传递、存储或传入导入的JS函数 return get_js_val_type(js_value); }
注意:__externref_t类型值不支持解引用、算术运算、与C指针/整数类型互转,仅可作为不透明值传递。
2. 从JavaScript端调用该C函数
实例化Wasm模块时需要开启referenceTypes特性,导出的C函数可以直接接收任意JavaScript值作为externref参数,无需额外转换。
示例代码:
// 实例化配置,开启reference types支持 const importObject = { env: {} }; const wasmInstance = await WebAssembly.instantiateStreaming( fetch('your_wasm_module.wasm'), importObject, { features: ['referenceTypes'] } ); // 直接传入任意JS值即可,会自动包装为externref传入C函数 const type1 = wasmInstance.exports.process_js_ref(1234); const type2 = wasmInstance.exports.process_js_ref("test string"); const type3 = wasmInstance.exports.process_js_ref({ key: "value" });
3. 在C代码中使用externref调用JavaScript导入函数
首先需要在C代码中声明导入的JS函数,指定导入的模块名和函数名,参数中使用__externref_t类型接收externref值,直接调用该声明函数即可传递externref到JS侧。
第一步:C侧声明导入函数
// 声明从env模块导入的get_js_val_type函数,输入externref,返回uint32_t __attribute__((import_module("env"), import_name("get_js_val_type"))) uint32_t get_js_val_type(__externref_t val);
第二步:JavaScript侧的importObject中提供对应实现
const importObject = { env: { get_js_val_type: (val) => { if (typeof val === 'number') return 1; if (typeof val === 'string') return 2; if (typeof val === 'object' && val !== null) return 3; return 0; } } };
额外注意事项
- 完整编译命令示例:
clang --target=wasm32 -mreference-types -O2 -nostdlib -Wl,--no-entry -o output.wasm your_code.c - 如果需要在C侧长期存储externref,需要声明
__externref_t类型的全局变量存储,不可存入普通整数/字符数组中,否则会导致引用失效。
内容的提问来源于stack exchange,提问作者eyelash
相关产品推荐
相关产品推荐

