go语言调用python_用python语言调用Go语言函数

用python语言调用Go语言函数

2020-07-16

宋洋葱

宋洋葱

c语言几乎是所有高级语言的桥梁,通过c语言编译的动态链接库(.so文件),其他高级语言即可调用c语言实现的功能,以便提高性能。

一般情况下,高级语言都实现了对动态链接库的调用支持。

比如用golang实现一个aes加密解密的功能,提供给python语言或者其他语言调用。

因为c的数据类型和golang不一致,因此在方法的参数和返回值上就需要做一层转换。否则golang实现的方法,C语言无法识别参数和返回值的类型。golang提供C模块处理这样的对应关系,也提供cgo这样的工具转换golang代码。

假设现在有个需求是:用python语言调用Go语言函数。

实现这样的功能需要以下几个步骤:

1、使用纯golang实现所需要的函数或功能

2、导入C模块,使用c语言支持的参数类型和返回值类型,包装一层需要导出的函数。

3、在上述需要导出的函数前面增加导出的注释//export yourfunc

举例,用golang实现一个字符串加密解密的功能,然后编译成静态链接库,供python调用。

1、go语言实现的加密解密:mycrypto.go

package main

func AESEncrypt(src string) (encrypted string) {

// your code

return encrypted

}

func AESDecrypt(encrypted string) (decrypted string) {

//your code

return decrypted

}

func main(){

//test

}

2、导入C模块,并包装需要导出的函数,并增加export encrypt注释

package main

import "C"

func AESEncrypt(src string) (encrypted string) {

// your code

return encrypted

}

func AESDecrypt(encrypted string) (decrypted string) {

//your code

return decrypted

}

//export encrypt

func encrypt(endata *C.char) *C.char {

ens := C.GoString(endata)

encrypted := AESEncrypt(ens)

return C.CString(encodedStr)

}

//export decypt

func decypt(dedata *C.char) *C.char{

des := C.GoString(dedata)

decrypted := AESDecrypt(des)

return C.CString(decrypted)

}

func main(){

//test

}

3、编译

go build -buildmode=c-shared -o mycrypto.so mycrypto.go

mkdir -p ./lib/linux-amd64

mv mycrypto.so mycrypto.so.h ./lib/linux-amd64

此时会生成mycrypto.so、mycrypto.h文件。

不同计算机平台编译的.so文件不能在其他平台使用,如linux编译的.so不能在windows下使用。

4、python调用动态链接库

为了把c语言的各种数据类型转换成python支持的类型,需要用到ctypes

import ctypes

lib = ctypes.cdll.LoadLibrary("./lib/linux-amd64/mycrypto.so")

lib.encrypt.restype = ctypes.c_char_p

lib.encrypt.argtype = ctypes.c_char_p

lib.decypt.restype = ctypes.c_char_p

lib.decypt.argtype = ctypes.c_char_p

def encrypt(txt):

res = lib.encrypt(txt.encode("utf-8"))

return res.decode()

def decypt(code):

res = lib.decypt(code.encode("utf-8"))

return res.decode()

到此大功告成,其他语言如R、Java、php等也可调用.so,大家可自行搜索实现。

注意点:

编写c语言支持的导出函数需要处理参数和返回值类型,必须是c支持的类型。

其他语言调用的时候,如string类型必须序列化(如:python的str.encode()),不可直接调用。

参考文献:

你可能感兴趣的:(go语言调用python)