PyGo [WIP] / [POC]
A small library exposing a helper decorator to ease the call of a go shared library from python.
Installation
python setup.py install
Get started
How to call go from python with this lib:
mygolib.go
:
edit your go lib package main
// #include <stdlib.h>
import "C"
import (
"fmt"
"unsafe"
)
//export myGoFunc
func myGoFunc(carg *C.char) *C.char {
goarg := C.GoString(carg)
return C.CString(fmt.Sprintf("hello %s", goarg))
}
//export freeMem
func freeMem(c *C.void) {
C.free(unsafe.Pointer(c))
}
func main() {}
, build it:
$ go build -o ./mygolib.so -buildmode=c-shared mygolib.go
, use it
edit your main.py
import pygo
@pygo.gofunc(lib="mygolib.so")
def myGoFunc(string_1, *string): pass
@pygo.gofunc(lib="mygolib.so", sig="string,string", fname="myGoFunc")
def test1(): pass
@gofunc(lib="tests/mygolib.so", fname="myGoFunc")
def test2(c_char_p_1, *c_char_p): pass
if __name__ == '__main__':
res = myGoFunc("world")
print( res))
res = test1("world")
print( res))
res = test2("world".encode('utf-8'))
print( res.decode('utf-8'))
, run it
$ python3 main.py
hello world
hello world
hello world
Go Generation !
There's also a go binary tool named pygo
which you can use to generate everything.
Look at ./tests/mylibgo/mygolib.go.
it contains a //go:generate pygo
, and some funcs have a @pygo.export
annotation.
All exported funcs (with an upper capital) which have been annotated will be:
- exported in a small library generated in the
mypkg/mylib/pygo
path, - along with the corresponding
.so
file, - and a
mypkg/mylib/pygo/mylib.py
python file that you can import from any python package
From:
/* this func is exported
* @pygo.export
*/
func Test0() {
return
}
//@pygo.export
func Test1(arg string) {
return
}
//@pygo.export
func Test2(arg string) int {
return 0
}
You run:
PYGO_LOG=INFO go generate -v ./...
And you get:
// Code generated by go generate; DO NOT EDIT.
// This file was generated by pygo at
// 2021-11-24 20:04:28.322044945 +0000 UTC m=+0.003300657
package main
import (
"C"
"github.com/yanndegat/pygo/tests/mylibgo"
)
//export Test0
func Test0() {
mygolib.Test0()
}
//export Test1
func Test1(arg *C.char) {
mygolib.Test1(C.GoString(arg))
}
//export Test2
func Test2(arg *C.char) int {
return mygolib.Test2(C.GoString(arg))
}
And
# Code generated by go generate; DO NOT EDIT.
# This file was generated by pygo at
# 2021-11-24 20:04:28.322456268 +0000 UTC m=+0.003711937
from pygo import gofunc
@gofunc(lib="_mygolib.so")
def Test0(): pass
@gofunc(lib="_mygolib.so")
def Test1(string_0): pass
@gofunc(lib="_mygolib.so")
def Test2(string_0, *int): pass
Motivation
Hopefully, this lib could help one convert a python codebase to go incrementally.