python调用golang
python调用golang脚本,中间需要通过cgo进行
-
golang部分
-
需要先导入cgo和一些标准库
import ( "fmt" "quote/node_exporter" "unsafe" ) /* #cgo CFLAGS: #include <stdio.h> #include <stdlib.h> */ import "C" //需要紧挨着
-
暴露一些golang函数
- 注意:
- // 和export 必须要紧挨着
- 如果需要传参的话,需要用c的类型
字符串用*C.char,go的函数接受使用的时候必须要转化成go的string类型,用C.GoString进行转换,返回字符串类型时也必须要用*C.char类型 用C.CString转换 - cgo 必须要对*C.char类型的变量进行释放,不然会引起内存泄漏,用C.free(unsafe.Pointer(restring)) 方式释放,但是不能提前释放,否则python调用的时候会出现乱码的情况
//export必须要放在函数上方,后面接上python调用的函数名称 //export get_stat_info def get_stat_info(quote *C.char) *C.char { var ( resString *C.char res = make(map[string]string) mapString string ) quoteS := C.GoString(quote) defer C.free(unsafe.Pointer(resString)) stat, err := node_exporter.GetStatInfo(quoteS) if err != nil { errF := fmt.Sprintf("couldn't get net stat info: %v", err) res["code"] = "1" res["content"] = errF mapString = node_exporter.ProcessMap(res) resString = C.CString(mapString) return resString } if stat == "" { errF := fmt.Sprintf("quote not exist: %v", quoteS) res["code"] = "1" res["content"] = errF mapString = node_exporter.ProcessMap(res) resString = C.CString(mapString) return resString } res["code"] = "0" res["content"] = stat mapString = node_exporter.ProcessMap(res) resString = C.CString(mapString) return resString } }
- 注意:
-
编译部分
在写完golang脚本之后需要将脚本编译成二进制文件
例:
go build -buildmode=c-shared -o quote.so quote.go
上面的命令会生成一个quote.so的二进制文件
-
-
python部分
-
python调用golang的二进制文件
-
导入ctypes模块
- 通过CDLL方法load二进制文件的库
- 需要导入ctypes中的数据类型,指定函数返回的结果类型为c的char类型
- 如果需要传入参数,需要进行转化一下,统一成utf编码
import ctypes from ctypes import * quotes = ctypes.CDLL("./quote.so") # c_char_p c的char类型 get_stat_info = quotes.get_stat_info get_stat_info.restype = c_char_p quote_string = "node_disk_io_now".encode("utf-8") res = get_stat_info(quote_string)
-
-