go语言的`plugin`调用还是很繁琐,而且功能限制也不少,我开发了的这个程序包含一个包`github.com/rocket049/pluginloader`和一个命令行工具`github.com/rocket049/pluginloader/cmd/pluginwrap`。
包`github.com/rocket049/pluginloader`引用到程序中,用于简化函数调用。
命令行工具`pluginwrap`用于从`plugin`的源代码生成可导出对象`struct`对应的`interface`和可导出`func`。
### 使用`pluginloader`
安装命令: `go get github.com/rocket049/pluginloader`
#### 可调用的函数:
```
type PluginLoader struct {
P *plugin.Plugin
}
///Call return type must be: (res,error)
func (p *PluginLoader) Call(funcName string, p0 ...interface{}) (interface{}, error)
//CallValue Allow any number of return values,return type: []reflect.Value,error
func (p *PluginLoader) CallValue(funcName string, p0 ...interface{}) ([]reflect.Value, error)
//MakeFunc point a func ptr to plugin
func (s *PluginLoader) MakeFunc(fptr interface{}, name string) error
```
#### `pluginloader`导出`method`的具体说明
- Call,直接通过函数名调用对应的函数,但是返回值形式受到限制。
- CallValue,直接通过函数名调用对应的函数,返回值形式不受限制。
- MakeFunc,根据名字把预定义的函数类型变量指向插件中的函数。
#### 调用示例
```
import "github.com/rocket049/pluginloader"
p, err := pluginloader.NewPluginLoader( "foo.so" )
if err != nil {
panic(err)
}
res, err := p.Call("NameOfFunc", p0,p1,p3,...)
// ...
ret := p.CallValue("NameOfFunc", p0,p1,p3,...)
// ...
var Foo func(arg string)(string,error)
p.MakeFunc(&Foo,"Foo")
ret, err = Foo("something")
// ...
```
### 使用`pluginwrap`
安装命令: `go get github.com/rocket049/pluginloader/cmd/pluginwrap`
#### 用法
`pluginwrap path/to/plugin/foo`
生成的文件名字:
`fooWrap.go`
把这个文件加入你的工程就可以方便的调用`plugin`的导出函数了。
#### 功能
1. 生成导出对象的接口,以便用于类型断言。
2. 生成导出函数。
#### 限制
本程序基于标准包`plugin`和`reflect`实现,因为`go`语言的变量类型转换的使用有很多限制,所以本程序对导出函数的参数类型、返回值类型都有限制, ***仅限于导出参数、返回值都是`builtin`类型的函数。***
如果导出函数的参数或返回值使用了其他复杂类型,请使用 `pluginloader.Call` 或 `pluginloader.CallValue` 调用。
#### 示例
```
// foo.so export funcs: func Hello(s string) / func NewFoo()*Foo
p, err := pluginloader.NewPluginLoader("foo.so")
if err != nil {
panic(err)
}
// MUST call InitxxxFuncs(p) before call funcs, xxx = plugin名字
InitfooFuncs(p)
// call Hello
Hello("friend")
// call NewFoo
iface, err := p.Call("NewFoo")
if err != nil {
panic(err)
}
// convert return value to interface IFoo
foo := iface.(IFoo)
```
有疑问加站长微信联系(非本文作者)