(笔记迁移 @ 2020年)
早已忘记 C/C++ 中常用的动态链接库了。日常开发中,使用 Go 引入一个组件,常常是go get
引入其源码,放在一起编译。
Go 1.8 起也提供了动态链接库的功能。
因为看 HyperLedger Fabric 源码的关系,接触到这块,稍微记录下。
一、使用流程
这里有个demo可以参考下:https://github.com/vladimirvivien/go-plugin-example
作者写作时,Go 1.8,plugin特性尚不支持MacOS。目前(Go 1.11.4),是支持Linux/MacOS的。
1. 编译模块(module, .so)
go build -buildmode=plugin -o path/to/shared/object/file.so path/to/source/code.go
注意-buildmode=plugin
这个编译Flag。
2. 引入"plugin"
import "plugin"
3. 加载module
plug, err := plugin.Open("path/to/shared/object/file.so")
4. 查找symbol,比如exported function/variable
symGreeter, err := plug.Lookup("Greeter")
plug.Lookup的返回类型是Symbol,其实就是interface{},为了正常使用,需要做类型转换。
type Symbol interface{}
5. 类型转换 type assertion
var greeter Greeter
greeter, ok := symGreeter.(Greeter)
很重要,不然没法使用。
6. 正常使用
greeter.Greet()
二、已知问题
无法debug
分别在MacOS和Ubuntu尝试debug使用plugin包的应用,报错如下(Go 1.11.4):
- MacOS, could not launch process: decoding dwarf section info at offset 0x0: too short
- Linux, could not launch process: could not get .debug_frame section: could not find .debug_frame section
使用gvm安装了其他Go版本尝试,no luck。
算是已知bug,一些issue如下:
- 官方说1.12会修复 https://github.com/golang/go/issues/23733
Go 1.12
Go 1.12发布了。看release notes并没有提到这块 https://golang.org/doc/go1.12 。
尝试下:
go build -buildmode=plugin -o eng/eng.so eng/greeter.go
dlv debug greeter.go
这次报错信息变了:
plugin.Open("./eng/eng"): plugin was built with a different version of package math/bits Process 64622 has exited with status 1
TBC.
三、总结
目前plugin特性还不够稳定,谨慎使用。
四、在Fabric中的应用
https://hyperledger-fabric.readthedocs.io/en/latest/systemchaincode.html
system chaincode
system chaincode是作为plugin引入的。 一例:
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package main
import (
"github.com/hyperledger/fabric/core/chaincode/shim"
pb "github.com/hyperledger/fabric/protos/peer"
)
// New returns an implementation of the chaincode interface
func New() shim.Chaincode {
return &scc{}
}
type scc struct{}
// Init implements the chaincode shim interface
func (s *scc) Init(stub shim.ChaincodeStubInterface) pb.Response {
return shim.Success(nil)
}
// Invoke implements the chaincode shim interface
func (s *scc) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
return shim.Success(nil)
}
func main() {}
倒是应用层的chaincode不需要实现New方法,只要实现一个interface的两个方法即可。
peer/orderer operation implementation
另外一个是peer中的auth、endorer等操作的实现也是通过plugin加载进来的。
这是过度设计吧。有plugin形式,也有编译形式的。
加密服务
BCCSP(Blockchain crypto provider))也是plugin.
// BCCSP is the blockchain cryptographic service provider that offers // the implementation of cryptographic standards and algorithms.。
Last modified on 2019-03-04