|
|
@@ -2,66 +2,148 @@ package main
|
|
|
|
|
|
import (
|
|
|
"fmt"
|
|
|
+ "sync"
|
|
|
|
|
|
"github.com/tliron/py4go"
|
|
|
"github.com/tliron/py4go/examples/hello-world/api"
|
|
|
)
|
|
|
|
|
|
-func main() {
|
|
|
- python.PrependPythonPath(".")
|
|
|
-
|
|
|
- python.Initialize()
|
|
|
- defer python.Finalize()
|
|
|
-
|
|
|
+func version() {
|
|
|
fmt.Printf("Go >> Python version:\n%s\n", python.Version())
|
|
|
- fmt.Println()
|
|
|
+}
|
|
|
|
|
|
+func typeChecking() {
|
|
|
fmt.Println("Go >> Type checking:")
|
|
|
float, _ := python.NewPrimitiveReference(1.0)
|
|
|
fmt.Printf("Go >> IsFloat: %t\n", float.IsFloat())
|
|
|
- fmt.Println()
|
|
|
-
|
|
|
- api, _ := api.CreateModule()
|
|
|
- api.EnableModule()
|
|
|
- defer api.Release()
|
|
|
-
|
|
|
- foo, _ := python.Import("foo")
|
|
|
- defer foo.Release()
|
|
|
+}
|
|
|
|
|
|
+func callPythonFunction(module *python.Reference) {
|
|
|
fmt.Println("Go >> Calling a Python function:")
|
|
|
- hello, _ := foo.GetAttr("hello")
|
|
|
+
|
|
|
+ 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_)
|
|
|
- fmt.Println()
|
|
|
+}
|
|
|
|
|
|
+func callPythonMethod(module *python.Reference) {
|
|
|
fmt.Println("Go >> Calling a Python method:")
|
|
|
- person, _ := foo.GetAttr("person")
|
|
|
+
|
|
|
+ person, _ := module.GetAttr("person")
|
|
|
defer person.Release()
|
|
|
+
|
|
|
greet, _ := person.GetAttr("greet")
|
|
|
defer greet.Release()
|
|
|
+
|
|
|
greet.Call()
|
|
|
- fmt.Println()
|
|
|
+}
|
|
|
|
|
|
+func getPythonException(module *python.Reference) {
|
|
|
fmt.Println("Go >> Python exception as Go error:")
|
|
|
- bad, _ := foo.GetAttr("bad")
|
|
|
+
|
|
|
+ bad, _ := module.GetAttr("bad")
|
|
|
defer bad.Release()
|
|
|
+
|
|
|
if _, err := bad.Call(); err != nil {
|
|
|
fmt.Printf("Go >> Error message: %s\n", err)
|
|
|
}
|
|
|
- fmt.Println()
|
|
|
+}
|
|
|
|
|
|
- goodbye, _ := foo.GetAttr("goodbye")
|
|
|
+func callGoFromPython(module *python.Reference) {
|
|
|
+ goodbye, _ := module.GetAttr("goodbye")
|
|
|
defer goodbye.Release()
|
|
|
goodbye.Call()
|
|
|
|
|
|
- sayName, _ := foo.GetAttr("say_name")
|
|
|
+ sayName, _ := module.GetAttr("say_name")
|
|
|
defer sayName.Release()
|
|
|
sayName.Call()
|
|
|
|
|
|
- sayNameFast, _ := foo.GetAttr("say_name_fast")
|
|
|
+ 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)
|
|
|
+}
|