如何通过wasmtime-dotnet向WebAssembly传递函数?
解决方案
问题根源
你遇到的核心问题是:C代码编译时默认未启用WASM的Reference Types扩展,导致函数指针被编译为i32(整数类型)而非WASM标准的funcref(函数引用类型);而wasmtime-dotnet中动态创建的Function实例对应funcref,无法直接与i32类型兼容。
步骤1:修改C代码并启用Reference Types编译
首先调整C函数签名为明确的函数指针类型(避免用void*模糊类型),并在编译时开启Reference Types扩展:
修改后的C代码
__attribute__((export_name("add_func"))) void add_func(void (*callback)()) { // 直接将callback传递给期望函数指针的C库API }
编译命令(WASI SDK)
添加-mreference-types参数,让编译器生成funcref类型的参数:
clang --target=wasm32-wasi -mreference-types -o module.wasm module.c
步骤2:在wasmtime-dotnet中正确传递动态函数
此时WASM模块的add_func参数类型为funcref,可以直接用Function类型传递:
using var store = new Store(); var module = Module.FromFile(store.Engine, "module.wasm"); var instance = new Instance(store, module, Array.Empty<object>()); // 创建动态回调函数 var dynamicCallback = Function.FromCallback(store, (caller, args, results) => { // 实现你的回调逻辑 Console.WriteLine("动态函数被调用"); }); // 获取并调用add_func var addFunc = instance.GetAction<Function>("add_func"); addFunc?.Invoke(dynamicCallback);
特殊场景:必须保留void*参数
如果因兼容现有C库必须使用void*,需要启用非标准的ref.as_i32扩展(需确认WASI SDK支持),但这种方式不推荐:
修改C代码
__attribute__((export_name("add_func"))) void add_func(void* func_ptr) { void (*callback)() = (void (*)())func_ptr; // 使用或传递callback }
编译命令
添加-mref-as-i32参数:
clang --target=wasm32-wasi -mreference-types -mref-as-i32 -o module.wasm module.c
C#侧处理
需通过WASM模块内的辅助函数将funcref转换为i32,不能直接传递整数(宿主动态函数无模块内索引),这种方式复杂度高且兼容性差,优先推荐第一种方案。
内容的提问来源于stack exchange,提问作者IS4
相关产品推荐
相关产品推荐

