实现方法概述
因为go语言可以生成gcc可用的静态库,我们可以用go语言实现我们需要的功能,然后编译成静态库,再用C语言调用该静态库,包装成python3模块,然后编译成动态库供python3调用。
实例
下面用一个用go线程乱序打印五次字符串参数的函数作为示例。
go程序
文件名:tryme.go
代码:
package mainimport ( "fmt" "math/rand" "sync" "time")import "C" func runp(wg *sync.WaitGroup, str string) { defer wg.Done() t := rand.Intn(5) time.Sleep(time.Second * time.Duration(t)) fmt.Println(str) }//export Trymefunc Tryme(str string) { var wg sync.WaitGroup for i := 1; i <= 5; i++ { wg.Add(1) go runp(&wg, fmt.Sprintf("%v %v", i, str)) } wg.Wait()} func main() {}
编译命令:
go build -o tryme.a -ldflags="-s -w" -buildmode=c-archive tryme.go
结果会生成2个文件:
tryme.a
tryme.h
C包装程序
文件名:topy.c
代码:
#include <Python.h> #include "tryme.h" #include "string.h" void trythis(char *s){ GoString gs = {s,strlen(s)}; Tryme(gs); } //add wrapped function static PyObject* wrap_trythis(PyObject *self, PyObject *args) { //Convert the python input objects into C objects char *s; if(!PyArg_ParseTuple(args, "s", &s)){ return NULL; } //Call c function trythis(s); //wrap the result from c function to python object. return (PyObject*)Py_BuildValue(""); } //define the PyMethodDef methods static PyMethodDef wrap_methods[] ={ {"trythis", (PyCFunction)wrap_trythis, METH_VARARGS,NULL}, {NULL, NULL} }; struct module_state { PyObject *error; }; static struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, "topy", NULL, sizeof(struct module_state), wrap_methods, NULL, NULL, NULL, NULL }; //initilization function PyMODINIT_FUNC PyInit_topy(void) { PyObject *module = PyModule_Create(&moduledef); return module; }
编译命令:
gcc -c -I/usr/include/python3.6m -fpic topy.c
gcc -o topy.so -shared -lpthread topy.o tryme.a
结果生成动态库: topy.so
用python3调用topy库
代码:
import topy topy.trythis("hello boy.")
结果输出(顺序随机):
4 hello boy. 5 hello boy. 2 hello boy. 1 hello boy. 3 hello boy.
结语
在网络编程、多线程编程等方面,go语言有这极大的优越性,非常适合用来扩展python3。
作者:从火星来
链接:https://www.jianshu.com/p/40e069954804
点击查看更多内容
为 TA 点赞
评论
共同学习,写下你的评论
评论加载中...
作者其他优质文章
正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦