2019-5-11 新增:
UnknownObject 類型增加了兩個(gè)新方法:Json
、CopyToStruct
玛歌,前一個(gè)導(dǎo)出JSON庄敛,后一個(gè)把結(jié)構(gòu)體的可導(dǎo)出值復(fù)制到另一個(gè)相似的結(jié)構(gòu)體中之碗。
2019-4-19 新修改:
- 修改
pluginwrap
,刪除生成的文件中的InitxxxFuncs
,改為:func GetxxxFuncs(p *pluginloader.PluginLoader) *xxxFuncs
低匙, 函數(shù)都被包含在xxxFuncs
結(jié)構(gòu)體中避免命名沖突漫拭。 -
pluginloader
新增用于調(diào)用未定義結(jié)構(gòu)體的對象:UnknownObject。
2019-4-18 新修改:pluginwrap幾乎已經(jīng)完美了下翎! 現(xiàn)在除了用戶自定義類型缤言,已經(jīng)可以使用所有被導(dǎo)入庫的類型。
go語言的plugin
調(diào)用還是很繁瑣视事,而且功能限制也不少胆萧,我開發(fā)了的這個(gè)程序包含一個(gè)包github.com/rocket049/pluginloader
和一個(gè)命令行工具github.com/rocket049/pluginloader/cmd/pluginwrap
。
包github.com/rocket049/pluginloader
引用到程序中郑口,用于簡化函數(shù)調(diào)用鸳碧。
命令行工具pluginwrap
用于從plugin
的源代碼生成可導(dǎo)出對象struct
對應(yīng)的interface
和可導(dǎo)出func
。
使用pluginloader
安裝命令: go get github.com/rocket049/pluginloader
可調(diào)用的函數(shù):
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' 必須是結(jié)構(gòu)體指針的 Value: *struct{...}
type UnknownObject struct {
V reflect.Value
}
//NewUnknownObject 參數(shù)'v' 必須是結(jié)構(gòu)體指針的 Value: *struct{...}犬性,否則返回 nil
func NewUnknownObject(v reflect.Value) *UnknownObject
//Get 得到結(jié)構(gòu)體成員的 Value
func (s *UnknownObject) Get(name string) reflect.Value
//Call 運(yùn)行結(jié)構(gòu)體的 method
func (s *UnknownObject) Call(fn string, args ...interface{}) []reflect.Value
//Json 把結(jié)構(gòu)體編碼為 JSON瞻离。 convert the struct to JSON. if error,return nil.
func (s *UnknownObject) Json() []byte
//CopyToStruct 利用 reflect 技術(shù)把結(jié)構(gòu)體的可 export 值復(fù)制到 v 中,v 必須是相似結(jié)構(gòu)體的指針乒裆。 copy the exported value of a struct to v
func (s *UnknownObject) CopyToStruct(v interface{}) error
pluginloader
導(dǎo)出method
的具體說明
- Call套利,直接通過函數(shù)名調(diào)用對應(yīng)的函數(shù),但是返回值形式受到限制鹤耍。
- CallValue肉迫,直接通過函數(shù)名調(diào)用對應(yīng)的函數(shù),返回值形式不受限制稿黄。
- MakeFunc喊衫,根據(jù)名字把預(yù)定義的函數(shù)類型變量指向插件中的函數(shù)。
UnknownObject
說明
-
func NewUnknownObject(v reflect.Value) *UnknownObject
杆怕,參數(shù)'v' 必須是結(jié)構(gòu)體指針的 Value: *struct{...}族购,否則返回 nil - Method:
Get(name string) reflect.Value
壳贪,得到結(jié)構(gòu)體成員的 Value - Method:
Call(fn string, args ...interface{}) []reflect.Value
,運(yùn)行結(jié)構(gòu)體的 method
調(diào)用示例
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
把這個(gè)文件加入你的工程就可以方便的調(diào)用plugin
的導(dǎo)出函數(shù)了寝杖。
功能
- 生成導(dǎo)出對象的接口违施,以便用于類型斷言。
- 生成導(dǎo)出函數(shù)瑟幕。
限制
本程序基于標(biāo)準(zhǔn)包plugin
和reflect
實(shí)現(xiàn)磕蒲,因?yàn)?code>go語言的變量類型轉(zhuǎn)換的使用有很多限制,所以本程序?qū)?dǎo)出函數(shù)的參數(shù)類型只盹、返回值類型都有限制辣往, 導(dǎo)出參數(shù)、返回值的類型僅限于基本類型鹿霸、標(biāo)準(zhǔn)庫排吴、第三方庫中的類型,不能使用自定義類型懦鼠。
如果必須使用自定義類型钻哩,有兩種辦法:
- 請使用
pluginloader.Call
或pluginloader.CallValue
調(diào)用。 - 把需要導(dǎo)出的復(fù)雜類型做成第三方庫(
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)