| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149 |
- package main
- import (
- "fmt"
- "sync"
- "github.com/tliron/py4go"
- "github.com/tliron/py4go/examples/hello-world/api"
- )
- func version() {
- fmt.Printf("Go >> Python version:\n%s\n", python.Version())
- }
- func typeChecking() {
- fmt.Println("Go >> Type checking:")
- float, _ := python.NewPrimitiveReference(1.0)
- fmt.Printf("Go >> IsFloat: %t\n", float.IsFloat())
- }
- func callPythonFunction(module *python.Reference) {
- fmt.Println("Go >> Calling a Python function:")
- hello, _ := module.GetAttr("hello")
- defer hello.Release()
- r, _ := hello.Call("Tal")
- defer r.Release()
- r_, _ := r.ToString()
- fmt.Printf("Go >> Python function returned: %s\n", r_)
- }
- func callPythonMethod(module *python.Reference) {
- fmt.Println("Go >> Calling a Python method:")
- person, _ := module.GetAttr("person")
- defer person.Release()
- greet, _ := person.GetAttr("greet")
- defer greet.Release()
- greet.Call()
- }
- func getPythonException(module *python.Reference) {
- fmt.Println("Go >> Python exception as Go error:")
- bad, _ := module.GetAttr("bad")
- defer bad.Release()
- if _, err := bad.Call(); err != nil {
- fmt.Printf("Go >> Error message: %s\n", err)
- }
- }
- func callGoFromPython(module *python.Reference) {
- goodbye, _ := module.GetAttr("goodbye")
- defer goodbye.Release()
- goodbye.Call()
- sayName, _ := module.GetAttr("say_name")
- defer sayName.Release()
- sayName.Call()
- sayNameFast, _ := module.GetAttr("say_name_fast")
- defer sayNameFast.Release()
- sayNameFast.Call()
- }
- func concurrency(module *python.Reference) {
- fmt.Println("Go >> Concurrency:")
- grow, _ := module.GetAttr("grow")
- defer grow.Release()
- func() {
- // Release Python's lock on our main thread, allowing other threads to execute
- // (Without this our calls to "grow", from other threads, will block forever)
- ts := python.SaveThreadState()
- defer ts.Restore()
- // Parallel work:
- var wg sync.WaitGroup
- defer wg.Wait()
- for i := 0; i < 5; i++ {
- wg.Add(1)
- go func() {
- defer wg.Done()
- for i := 0; i < 100; i++ {
- // We must manually acquire Python's Global Interpreter Lock (GIL),
- // because Python doesn't know about our Go "threads" (goroutines)
- gs := python.EnsureGilState()
- defer gs.Release()
- // (Note: We could also have acquired the GIL outside of this for-loop;
- // it's really up to us, how we want to balance concurrency with the cost
- // of context switching)
- grow.Call(1)
- }
- }()
- }
- }()
- size, _ := module.GetAttr("size")
- defer size.Release()
- size_, _ := size.ToInt64()
- fmt.Printf("Go >> Size is %d\n", size_)
- }
- func main() {
- python.PrependPythonPath(".")
- python.Initialize()
- defer python.Finalize()
- version()
- fmt.Println()
- typeChecking()
- fmt.Println()
- api, _ := api.CreateModule()
- defer api.Release()
- api.EnableModule()
- foo, _ := python.Import("foo")
- defer foo.Release()
- callPythonFunction(foo)
- fmt.Println()
- callPythonMethod(foo)
- fmt.Println()
- getPythonException(foo)
- fmt.Println()
- callGoFromPython(foo)
- fmt.Println()
- concurrency(foo)
- }
|