在写AGV调度的时候发现python的并发调度性能不是很高,并且会有很多调度线程挂掉的事件发生,所以想利用Go的高并发去做一些可行的调度,就想到了去写一个go版本的调度控制给py调用,由此,开始搞一个小demo记录一下
还是老规矩,用了ubuntu18的系统,以ubuntu18为主
先去下一下官网的包,我下的版本是go1.13.4.linux-amd64
下好之后随便解压个位置,比如
tar xf go1.13.4.linux-amd64.tar.gz -C /home/用户名/go
解压到/home/用户名/go文件夹下,需要配置全局变量
sudo vim ~/.bashrc
在最后一行加上两行配置
export GOPATH=/home/用户名/go
export PATH=$GOPATH/bin:$PATH
就不多说了这俩。。
验证一下是否成功
go version
成功的话,返回如下
go version go1.13.4.linux-amd64
go程序编写就不多说了,文档也很多,就简单的写个返回字符串函数
package main
import "C"
//export GetName
func GetName() *C.char{
return C.CString("symoon is so cool")
}
func main(){
}
首先build的镜像需要导入C库,原因是因为字符串类型不互通,需要把返回的字符串转成C string,道理就不多说了。
还有//export
这个是必须的,不声明的话此函数无法在动态库中被调用,无法生成相应.h
文件
当前代码文件main.go
,所以我们直接执行
go build -buildmode=c-shared -o test.so main.go
执行后生成test.so
动态库文件,根据不同系统生成不一样这个就不多说了。
这个balabala就不说了吧。。。
sudo apt install python3
接下来直接写代码吧vim test.py
import ctypes
lib = ctypes.CDLL("./test.so")
msg = lib.GetName
msg.restype = ctypes.c_char_p
msg_b=msg()
print(msg_b.decode("utf-8"))
也非常简单,返回的是字节,转成字符串就可以了,所以在Go里面执行业务也是没问题的,传参也需要转类型balabala...
因为在调用go的动态库时候,我们往往希望向里面传递json数据,然而go的string和c的string是需要转换的,所以,直接贴一下代码吧
package main
import "C"
import (
"encoding/json"
_"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"strings"
)
//export Dic
type Dic struct {
Msg string
Cookie string
}
//export GetName
func GetName(pyStr *C.char) *C.char{
fmt.Println(C.GoString(pyStr))
var s Dic
err:=json.Unmarshal([]byte(C.GoString(pyStr)),&s)
if err!=nil{
fmt.Println(err)
}
fmt.Println(s)
return C.CString(s.Msg)
}
func main(){
}
go build -buildmode=c-shared -o test.so main.go
这里有一点要注意,写好结构体,接取json字符串就行了,然后就,变成go可用的对象了,接下来上python
这里边也没啥好说的了,就是传递的时候一定要传二进制
import ctypes, json
lib = ctypes.CDLL("./test.so")
dic = {
"msg": "hello , here is symoon", "cookie":"balabala"
}
msg = lib.GetName
msg.restype = ctypes.c_char_p
msg_b = msg(json.dumps(dic).encode('utf-8'))
print(msg_b.decode("utf-8"))
最后运行结果就是hello, here is symoon