main.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. package main
  2. import (
  3. "fmt"
  4. "sync"
  5. "github.com/tliron/py4go"
  6. "github.com/tliron/py4go/examples/hello-world/api"
  7. )
  8. func version() {
  9. fmt.Printf("Go >> Python version:\n%s\n", python.Version())
  10. }
  11. func typeChecking() {
  12. fmt.Println("Go >> Type checking:")
  13. float, _ := python.NewPrimitiveReference(1.0)
  14. fmt.Printf("Go >> IsFloat: %t\n", float.IsFloat())
  15. }
  16. func callPythonFunction(module *python.Reference) {
  17. fmt.Println("Go >> Calling a Python function:")
  18. hello, _ := module.GetAttr("hello")
  19. defer hello.Release()
  20. r, _ := hello.Call("Tal")
  21. defer r.Release()
  22. r_, _ := r.ToString()
  23. fmt.Printf("Go >> Python function returned: %s\n", r_)
  24. }
  25. func callPythonMethod(module *python.Reference) {
  26. fmt.Println("Go >> Calling a Python method:")
  27. person, _ := module.GetAttr("person")
  28. defer person.Release()
  29. greet, _ := person.GetAttr("greet")
  30. defer greet.Release()
  31. greet.Call()
  32. }
  33. func getPythonException(module *python.Reference) {
  34. fmt.Println("Go >> Python exception as Go error:")
  35. bad, _ := module.GetAttr("bad")
  36. defer bad.Release()
  37. if _, err := bad.Call(); err != nil {
  38. fmt.Printf("Go >> Error message: %s\n", err)
  39. }
  40. }
  41. func callGoFromPython(module *python.Reference) {
  42. goodbye, _ := module.GetAttr("goodbye")
  43. defer goodbye.Release()
  44. goodbye.Call()
  45. sayName, _ := module.GetAttr("say_name")
  46. defer sayName.Release()
  47. sayName.Call()
  48. sayNameFast, _ := module.GetAttr("say_name_fast")
  49. defer sayNameFast.Release()
  50. sayNameFast.Call()
  51. }
  52. func concurrency(module *python.Reference) {
  53. fmt.Println("Go >> Concurrency:")
  54. grow, _ := module.GetAttr("grow")
  55. defer grow.Release()
  56. func() {
  57. // Release Python's lock on our main thread, allowing other threads to execute
  58. // (Without this our calls to "grow", from other threads, will block forever)
  59. ts := python.SaveThreadState()
  60. defer ts.Restore()
  61. // Parallel work:
  62. var wg sync.WaitGroup
  63. defer wg.Wait()
  64. for i := 0; i < 5; i++ {
  65. wg.Add(1)
  66. go func() {
  67. defer wg.Done()
  68. for i := 0; i < 100; i++ {
  69. // We must manually acquire Python's Global Interpreter Lock (GIL),
  70. // because Python doesn't know about our Go "threads" (goroutines)
  71. gs := python.EnsureGilState()
  72. defer gs.Release()
  73. // (Note: We could also have acquired the GIL outside of this for-loop;
  74. // it's really up to us, how we want to balance concurrency with the cost
  75. // of context switching)
  76. grow.Call(1)
  77. }
  78. }()
  79. }
  80. }()
  81. size, _ := module.GetAttr("size")
  82. defer size.Release()
  83. size_, _ := size.ToInt64()
  84. fmt.Printf("Go >> Size is %d\n", size_)
  85. }
  86. func main() {
  87. python.PrependPythonPath(".")
  88. python.Initialize()
  89. defer python.Finalize()
  90. version()
  91. fmt.Println()
  92. typeChecking()
  93. fmt.Println()
  94. api, _ := api.CreateModule()
  95. defer api.Release()
  96. api.EnableModule()
  97. foo, _ := python.Import("foo")
  98. defer foo.Release()
  99. callPythonFunction(foo)
  100. fmt.Println()
  101. callPythonMethod(foo)
  102. fmt.Println()
  103. getPythonException(foo)
  104. fmt.Println()
  105. callGoFromPython(foo)
  106. fmt.Println()
  107. concurrency(foo)
  108. }