恐慌:运行时错误:cgo结果具有Go指针

huangapple go评论197阅读模式
英文:

panic: runtime error: cgo result has Go pointer

问题

你好,最近我尝试从Python代码中调用一个打印一些除法结果的Golang函数,该函数使用for循环。以下是recap.go的完整代码:

  1. package main
  2. import (
  3. "C"
  4. "strconv"
  5. )
  6. //export PrintAlg
  7. func PrintAlg(debug bool) string {
  8. var b200 int = 0
  9. var b300 int = 0
  10. var b400 int = 0
  11. var x string = "A"
  12. if debug == true {
  13. // extra
  14. } else if debug == false {
  15. for i := 1; i <= 100; i++ {
  16. if i%4 == 0 && i%3 == 0 {
  17. b200++
  18. b300++
  19. b400++
  20. } else if i%4 == 0 && !(i%3 == 0) {
  21. b400++
  22. b200++
  23. } else if i%2 == 0 && i%3 == 0 && !(i%4 == 0) {
  24. b200++
  25. b300++
  26. } else if i%3 == 0 && !(i%2 == 0) && !(i%4 == 0) {
  27. b300++
  28. } else if i%2 == 0 && !(i%3 == 0) && !(i%4 == 0) {
  29. b200++
  30. } else if i%2 == 0 && i%3 == 0 && i%4 == 0 {
  31. b200++
  32. b300++
  33. b400++
  34. }
  35. }
  36. x = strconv.Itoa(b200) + " " + strconv.Itoa(b300) + " " + strconv.Itoa(b400)
  37. }
  38. return x
  39. }
  40. func main() {
  41. }

然后,我尝试使用CTYPES(在Python代码中)调用PrintAlg函数。当我从命令行运行Python代码时,出现了以下错误:

  1. panic: runtime error: cgo result has Go pointer
  2. goroutine 17 [running, locked to thread]:
  3. panic({0x67322a80, 0xc00004a0a0})
  4. C:/Program Files/Go/src/runtime/panic.go:1147 +0x3a8
  5. runtime.cgoCheckArg(0x67320da0, 0xc00004a090, 0x10, 0x0, {0x6732cc4f, 0x19})
  6. C:/Program Files/Go/src/runtime/cgocall.go:514 +0x4d8
  7. runtime.cgoCheckResult({0x67320da0, 0xc00004a090})
  8. C:/Program Files/Go/src/runtime/cgocall.go:630 +0x54
  9. _cgoexp_ba17693967af_PrintAlg(0x108efee9c0)
  10. _cgo_gotypes.go:39 +0x5a
  11. runtime.cgocallbackg1(0x67315640, 0x0, 0x0)
  12. C:/Program Files/Go/src/runtime/cgocall.go:306 +0x29a
  13. runtime.cgocallbackg(0x0, 0x0, 0x0)
  14. C:/Program Files/Go/src/runtime/cgocall.go:232 +0x106
  15. runtime.cgocallbackg(0x67315640, 0x108efee9c0, 0x0)
  16. &lt;autogenerated&gt;:1 +0x36
  17. runtime.cgocallback(0x0, 0x0, 0x0)
  18. C:/Program Files/Go/src/runtime/asm_amd64.s:915 +0xd7
  19. runtime.goexit()
  20. C:/Program Files/Go/src/runtime/asm_amd64.s:1581 +0x1

你可以如何修复这个错误?

英文:

Hello i was recently trying to call a golang function from python code that is printing some division things with for loop.

Full code of recap.go:

  1. package main
  2. import (
  3. &quot;C&quot;
  4. &quot;strconv&quot;
  5. )
  6. //export PrintAlg
  7. func PrintAlg(debug bool) string {
  8. var b200 int = 0
  9. var b300 int = 0
  10. var b400 int = 0
  11. var x string = &quot;A&quot;
  12. if debug == true {
  13. // extra
  14. } else if debug == false {
  15. for i := 1; i &lt;= 100; i++ {
  16. if i%4 == 0 &amp;&amp; i%3 == 0 {
  17. b200++
  18. b300++
  19. b400++
  20. } else if i%4 == 0 &amp;&amp; !(i%3 == 0) {
  21. b400++
  22. b200++
  23. } else if i%2 == 0 &amp;&amp; i%3 == 0 &amp;&amp; !(i%4 == 0) {
  24. b200++
  25. b300++
  26. } else if i%3 == 0 &amp;&amp; !(i%2 == 0) &amp;&amp; !(i%4 == 0) {
  27. b300++
  28. } else if i%2 == 0 &amp;&amp; !(i%3 == 0) &amp;&amp; !(i%4 == 0) {
  29. b200++
  30. } else if i%2 == 0 &amp;&amp; i%3 == 0 &amp;&amp; i%4 == 0 {
  31. b200++
  32. b300++
  33. b400++
  34. }
  35. }
  36. x = strconv.Itoa(b200) + &quot; &quot; + strconv.Itoa(b300) + &quot; &quot; + strconv.Itoa(b400)
  37. }
  38. return x
  39. }
  40. func main() {
  41. }

then i tryed to call PrintAlg function with CTYPES (in python code). Then when i ran the python code from cmd, this error occured:

  1. panic: runtime error: cgo result has Go pointer
  2. goroutine 17 [running, locked to thread]:
  3. panic({0x67322a80, 0xc00004a0a0})
  4. C:/Program Files/Go/src/runtime/panic.go:1147 +0x3a8
  5. runtime.cgoCheckArg(0x67320da0, 0xc00004a090, 0x10, 0x0, {0x6732cc4f, 0x19})
  6. C:/Program Files/Go/src/runtime/cgocall.go:514 +0x4d8
  7. runtime.cgoCheckResult({0x67320da0, 0xc00004a090})
  8. C:/Program Files/Go/src/runtime/cgocall.go:630 +0x54
  9. _cgoexp_ba17693967af_PrintAlg(0x108efee9c0)
  10. _cgo_gotypes.go:39 +0x5a
  11. runtime.cgocallbackg1(0x67315640, 0x0, 0x0)
  12. C:/Program Files/Go/src/runtime/cgocall.go:306 +0x29a
  13. runtime.cgocallbackg(0x0, 0x0, 0x0)
  14. C:/Program Files/Go/src/runtime/cgocall.go:232 +0x106
  15. runtime.cgocallbackg(0x67315640, 0x108efee9c0, 0x0)
  16. &lt;autogenerated&gt;:1 +0x36
  17. runtime.cgocallback(0x0, 0x0, 0x0)
  18. C:/Program Files/Go/src/runtime/asm_amd64.s:915 +0xd7
  19. runtime.goexit()
  20. C:/Program Files/Go/src/runtime/asm_amd64.s:1581 +0x1

what can i do for fixing this error?

答案1

得分: 1

Go运行时对字符串的实现是:

  1. type stringStruct struct {
  2. str unsafe.Pointer
  3. len int
  4. }

当你从Go的PrintAlg函数中返回时,即return x,Go会返回一个指向Go字符串x底层字节的Go内存实例stringStruct

  1. panic: runtime error: cgo result has Go pointer

阅读cgo文档,特别是Passing_pointers部分,了解详情。

在Go中,可以这样编写:

  1. func PrintAlg(debug bool) *C.char {
  2. // ...
  3. return C.CString(x)
  4. }

以返回一个指向C字符串实例的指针。在不再需要时释放指针。



  1. $ go build -buildmode=c-shared -o _recap.so
  2. $ python3 recap.py
  3. 50 33 25
  4. $

recap.go:

  1. package main
  2. import (
  3. "C"
  4. "strconv"
  5. )
  6. //export PrintAlg
  7. func PrintAlg(debug bool) *C.char {
  8. var b200 int = 0
  9. var b300 int = 0
  10. var b400 int = 0
  11. var x string = "A"
  12. if debug == true {
  13. // extra
  14. } else if debug == false {
  15. for i := 1; i <= 100; i++ {
  16. if i%4 == 0 && i%3 == 0 {
  17. b200++
  18. b300++
  19. b400++
  20. } else if i%4 == 0 && !(i%3 == 0) {
  21. b400++
  22. b200++
  23. } else if i%2 == 0 && i%3 == 0 && !(i%4 == 0) {
  24. b200++
  25. b300++
  26. } else if i%3 == 0 && !(i%2 == 0) && !(i%4 == 0) {
  27. b300++
  28. } else if i%2 == 0 && !(i%3 == 0) && !(i%4 == 0) {
  29. b200++
  30. } else if i%2 == 0 && i%3 == 0 && i%4 == 0 {
  31. b200++
  32. b300++
  33. b400++
  34. }
  35. }
  36. x = strconv.Itoa(b200) + " " + strconv.Itoa(b300) + " " + strconv.Itoa(b400)
  37. }
  38. return C.CString(x)
  39. }
  40. func main() {}

recap.py:

  1. import ctypes
  2. recap = ctypes.cdll.LoadLibrary('./_recap.so')
  3. printAlg = recap.PrintAlg
  4. printAlg.argtypes = [ctypes.c_bool]
  5. printAlg.restype = ctypes.c_void_p
  6. free = recap.free
  7. free.argtypes = [ctypes.c_void_p]
  8. px = printAlg(False)
  9. x = ctypes.string_at(px).decode('utf-8')
  10. free(px)
  11. print(x)
英文:

The Go runtime implementation of a string is

  1. type stringStruct struct {
  2. str unsafe.Pointer
  3. len int
  4. }

When you return from your Go PrintAlg function - return x - Go returns a Go memory instance of stringStruct which points to the underlying bytes of the Go string x.

  1. panic: runtime error: cgo result has Go pointer

Read the cgo documentation, especially Passing_pointers, for details.

In Go, write

  1. func PrintAlg(debug bool) *C.char {
  2. // ...
  3. return C.CString(x)
  4. }

to return a pointer to an instance of a C string. Free the pointer when no longer needed.



  1. $ go build -buildmode=c-shared -o _recap.so
  2. $ python3 recap.py
  3. 50 33 25
  4. $

recap.go:

  1. package main
  2. import (
  3. &quot;C&quot;
  4. &quot;strconv&quot;
  5. )
  6. //export PrintAlg
  7. func PrintAlg(debug bool) *C.char {
  8. var b200 int = 0
  9. var b300 int = 0
  10. var b400 int = 0
  11. var x string = &quot;A&quot;
  12. if debug == true {
  13. // extra
  14. } else if debug == false {
  15. for i := 1; i &lt;= 100; i++ {
  16. if i%4 == 0 &amp;&amp; i%3 == 0 {
  17. b200++
  18. b300++
  19. b400++
  20. } else if i%4 == 0 &amp;&amp; !(i%3 == 0) {
  21. b400++
  22. b200++
  23. } else if i%2 == 0 &amp;&amp; i%3 == 0 &amp;&amp; !(i%4 == 0) {
  24. b200++
  25. b300++
  26. } else if i%3 == 0 &amp;&amp; !(i%2 == 0) &amp;&amp; !(i%4 == 0) {
  27. b300++
  28. } else if i%2 == 0 &amp;&amp; !(i%3 == 0) &amp;&amp; !(i%4 == 0) {
  29. b200++
  30. } else if i%2 == 0 &amp;&amp; i%3 == 0 &amp;&amp; i%4 == 0 {
  31. b200++
  32. b300++
  33. b400++
  34. }
  35. }
  36. x = strconv.Itoa(b200) + &quot; &quot; + strconv.Itoa(b300) + &quot; &quot; + strconv.Itoa(b400)
  37. }
  38. return C.CString(x)
  39. }
  40. func main() {}

recap.py:

  1. import ctypes
  2. recap = ctypes.cdll.LoadLibrary(&#39;./_recap.so&#39;)
  3. printAlg = recap.PrintAlg
  4. printAlg.argtypes = [ctypes.c_bool]
  5. printAlg.restype = ctypes.c_void_p
  6. free = recap.free
  7. free.argtypes = [ctypes.c_void_p]
  8. px = printAlg(False)
  9. x = ctypes.string_at(px).decode(&#39;utf-8&#39;)
  10. free(px)
  11. print(x)

huangapple
  • 本文由 发表于 2022年3月12日 21:16:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/71450016.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定