A really great feature would be able to load a plugin from binary, instead of from filepath. This would be done by simply adding a method similar to Load on the generated plugin (and probably refactoring Load as well). Here's what it would look like in the example given in the README:
func (p *GreeterPlugin) Load(ctx context.Context, pluginPath string) (greeter, error) {
b, err := os.ReadFile(pluginPath)
if err != nil {
return nil, err
}
return p.LoadBinary(ctx, b)
}
func (p *GreeterPlugin) LoadBinary(ctx context.Context, pluginBinary []byte) (greeter, error) {
// Create a new runtime so that multiple modules will not conflict
r, err := p.newRuntime(ctx)
if err != nil {
return nil, err
}
// Compile the WebAssembly module using the default configuration.
code, err := r.CompileModule(ctx, pluginBinary)
if err != nil {
return nil, err
}
// InstantiateModule runs the "_start" function, WASI's "main".
module, err := r.InstantiateModule(ctx, code, p.moduleConfig)
if err != nil {
// Note: Most compilers do not exit the module after running "_start",
// unless there was an Error. This allows you to call exported functions.
if exitErr, ok := err.(*sys.ExitError); ok && exitErr.ExitCode() != 0 {
return nil, fmt.Errorf("unexpected exit_code: %d", exitErr.ExitCode())
} else if !ok {
return nil, err
}
}
// Compare API versions with the loading plugin
apiVersion := module.ExportedFunction("greeter_api_version")
if apiVersion == nil {
return nil, errors.New("greeter_api_version is not exported")
}
results, err := apiVersion.Call(ctx)
if err != nil {
return nil, err
} else if len(results) != 1 {
return nil, errors.New("invalid greeter_api_version signature")
}
if results[0] != GreeterPluginAPIVersion {
return nil, fmt.Errorf("API version mismatch, host: %d, plugin: %d", GreeterPluginAPIVersion, results[0])
}
sayhello := module.ExportedFunction("greeter_say_hello")
if sayhello == nil {
return nil, errors.New("greeter_say_hello is not exported")
}
malloc := module.ExportedFunction("malloc")
if malloc == nil {
return nil, errors.New("malloc is not exported")
}
free := module.ExportedFunction("free")
if free == nil {
return nil, errors.New("free is not exported")
}
return &greeterPlugin{
runtime: r,
module: module,
malloc: malloc,
free: free,
sayhello: sayhello,
}, nil
}
I'd be more than happy to submit a PR for this if you all would be ok with it.
A really great feature would be able to load a plugin from binary, instead of from filepath. This would be done by simply adding a method similar to
Load
on the generated plugin (and probably refactoringLoad
as well). Here's what it would look like in the example given in the README:I'd be more than happy to submit a PR for this if you all would be ok with it.