Happy Coding
Go Plugin

(笔记迁移 @ 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如下:

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