< >

    pluginloader:简化go语言plugin函数和对象调用

    2019-5-11 新增

    UnknownObject 类型增加了两个新方法:JsonCopyToStruct,前一个导出JSON,后一个把结构体的可导出值复制到另一个相似的结构体中。

    2019-4-19 新修改

    2019-4-18 新修改:pluginwrap几乎已经完美了! 现在除了用户自定义类型,已经可以使用所有被导入库的类型。

    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 
    
    //20190419 新增
    //UnknownObject 成员'V' 必须是结构体指针的 Value: *struct{...}
    type UnknownObject struct {
    	V reflect.Value
    }
    //NewUnknownObject 参数'v' 必须是结构体指针的 Value: *struct{...},否则返回 nil
    func NewUnknownObject(v reflect.Value) *UnknownObject 
    
    //Get 得到结构体成员的 Value
    func (s *UnknownObject) Get(name string) reflect.Value
    
    //Call 运行结构体的 method
    func (s *UnknownObject) Call(fn string, args ...interface{}) []reflect.Value
    
    //Json 把结构体编码为 JSON。 convert the struct to JSON. if error,return nil.
    func (s *UnknownObject) Json() []byte 
    
    //CopyToStruct 利用 reflect 技术把结构体的可 export 值复制到 v 中,v 必须是相似结构体的指针。 copy the exported value of a struct to v 
    func (s *UnknownObject) CopyToStruct(v interface{}) error 
    

    pluginloader导出method的具体说明

    UnknownObject说明

    调用示例

    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")
    // ...
    
    // 使用 UnknownObject. NewFoo return 'foo *Foo'
    v, err := p.CallValue("NewFoo")
    if err != nil {
    	t.Fatal(err)
    }
    obj := NewUnknownObject(v[0])
    
    id: = obj.Get("Id").Int()
    
    err = obj.Call("Set", nil)
    

    使用pluginwrap

    安装命令: go get github.com/rocket049/pluginloader/cmd/pluginwrap

    用法

    pluginwrap path/to/plugin/foo

    生成的文件名字: fooWrap.go

    把这个文件加入你的工程就可以方便的调用plugin的导出函数了。

    功能

    1. 生成导出对象的接口,以便用于类型断言。
    2. 生成导出函数。

    限制

    本程序基于标准包pluginreflect实现,因为go语言的变量类型转换的使用有很多限制,所以本程序对导出函数的参数类型、返回值类型都有限制, 导出参数、返回值的类型仅限于基本类型、标准库、第三方库中的类型,不能使用自定义类型。

    如果必须使用自定义类型,有两种办法:

    1. 请使用 pluginloader.Callpluginloader.CallValue 调用。
    2. 把需要导出的复杂类型做成第三方库(import "your/package"),不要在plugin源代码中定义。

    示例

    使用对象(struct)

    	p, err := pluginloader.NewPluginLoader("foo.so")
    	if err != nil {
    		panic(err)
    	}
    	iface, err := p.Call("NewFoo",arg...)
    	if err != nil {
    		panic(err)
    	}
    	foo := iface.(IFoo)
    	// use foo.Method
    

    使用func

    	//2090419 new
    	p, err := pluginloader.NewPluginLoader("foo.so")
    	if err != nil {
    		panic(err)
    	}
    	
    	// MUST call GetxxxFuncs(p) before call funcs, xxx = plugin名字
    	funcs := GetfooFuncs(p)
    	
    	// call methods in plugin foo
    	funcs.Method(arg)
    	
    
    备案号:苏ICP备19034936号    站长邮箱:fuhuizn@163.com

    苏公网安备 32050702010684号