使用Wasmex在Elixir中调用Go库Pdfcpu时遇导出函数未找到问题
问题描述
我在Elixir模块中尝试调用由Go编写的Pdfcpu库来修改现有PDF,该库提供CLI和API,我使用的是API。借助Wasmex运行WASM代码以实现与Elixir的交互。
编写的Go模块如下:
package main import ( "log" "github.com/pdfcpu/pdfcpu/pkg/api" ) func main() { } func RotateFile(inFile, outFile string, rotation int, selectedPages []string) { if err := api.RotateFile(inFile, outFile, rotation, []string{"1"}, nil); err != nil { log.Fatal(err) } }
执行编译命令:
go mod init proj/pdfcpu go get github.com/pdfcpu/pdfcpu@latest go mod tidy GOOS=wasip1 GOARCH=wasm go build -o main.go
测试用的Elixir脚本:
api_binary = File.read!("main.wasm") {:ok, api_pid} = Wasmex.start_link(%{bytes: api_binary, wasi: true}) Wasmex.call_function(api_pid, "RotateFile", ["input.pdf", "output.pdf", 180, [], nil])
运行后收到错误:{:error, "exported function RotateFile not found"},尝试调用api.RotateFile也无效。
错误原因与修正方案
1. Go函数未导出为WASM可调用接口
Go编译为WASM时,普通函数不会自动被导出到WASM的外部函数表中,必须通过特殊注释标记导出,同时要适配WASM的类型限制(仅支持基础数值类型,字符串、切片等复杂类型需通过syscall/js包处理)。
修正后的Go代码:
package main import ( "log" "syscall/js" "github.com/pdfcpu/pdfcpu/pkg/api" ) func main() { // 阻塞主线程,防止WASM实例启动后立即退出 <-make(chan bool) } //go:wasm-module pdfcpu //export RotateFile func RotateFile(this js.Value, args []js.Value) interface{} { // 参数校验 if len(args) < 4 { return "参数数量不足" } // 从JS参数中提取值 inFile := args[0].String() outFile := args[1].String() rotation := args[2].Int() // 转换页面列表参数 selectedPages := make([]string, args[3].Length()) for i := 0; i < args[3].Length(); i++ { selectedPages[i] = args[3].Index(i).String() } // 调用pdfcpu API if err := api.RotateFile(inFile, outFile, rotation, selectedPages, nil); err != nil { log.Println(err) return err.Error() } return nil }
2. 编译命令输出文件错误
原编译命令中-o main.go会覆盖Go源码文件,正确应该输出为.wasm格式文件:
GOOS=wasip1 GOARCH=wasm go build -o main.wasm
3. Elixir调用参数不符合绑定要求
Wasmex调用Go导出的WASM函数时,不能直接传递Elixir原生列表和nil,需要将复杂类型转换为WASM内存中的数组。修正后的Elixir脚本:
api_binary = File.read!("main.wasm") {:ok, api_pid} = Wasmex.start_link(%{bytes: api_binary, wasi: true}) # 将页面列表转换为WASM可识别的数组 selected_pages = Wasmex.Memory.create_array(api_pid, ["1"]) result = Wasmex.call_function(api_pid, "RotateFile", ["input.pdf", "output.pdf", 180, selected_pages]) IO.inspect(result)
内容的提问来源于stack exchange,提问作者Paul B
相关产品推荐
相关产品推荐

