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

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

panic: runtime error: cgo result has Go pointer

问题

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

package main

import (
	"C"
	"strconv"
)

//export PrintAlg
func PrintAlg(debug bool) string {
	var b200 int = 0
	var b300 int = 0
	var b400 int = 0
	var x string = "A"
	if debug == true {
		// extra
	} else if debug == false {
		for i := 1; i <= 100; i++ {
			if i%4 == 0 && i%3 == 0 {
				b200++
				b300++
				b400++
			} else if i%4 == 0 && !(i%3 == 0) {
				b400++
				b200++
			} else if i%2 == 0 && i%3 == 0 && !(i%4 == 0) {
				b200++
				b300++
			} else if i%3 == 0 && !(i%2 == 0) && !(i%4 == 0) {
				b300++
			} else if i%2 == 0 && !(i%3 == 0) && !(i%4 == 0) {
				b200++
			} else if i%2 == 0 && i%3 == 0 && i%4 == 0 {
				b200++
				b300++
				b400++
			}
		}
		x = strconv.Itoa(b200) + " " + strconv.Itoa(b300) + " " + strconv.Itoa(b400)
	}
	return x
}

func main() {

}

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

panic: runtime error: cgo result has Go pointer
goroutine 17 [running, locked to thread]:
panic({0x67322a80, 0xc00004a0a0})
C:/Program Files/Go/src/runtime/panic.go:1147 +0x3a8
runtime.cgoCheckArg(0x67320da0, 0xc00004a090, 0x10, 0x0, {0x6732cc4f, 0x19})
C:/Program Files/Go/src/runtime/cgocall.go:514 +0x4d8
runtime.cgoCheckResult({0x67320da0, 0xc00004a090})
C:/Program Files/Go/src/runtime/cgocall.go:630 +0x54
_cgoexp_ba17693967af_PrintAlg(0x108efee9c0)
_cgo_gotypes.go:39 +0x5a
runtime.cgocallbackg1(0x67315640, 0x0, 0x0)
C:/Program Files/Go/src/runtime/cgocall.go:306 +0x29a
runtime.cgocallbackg(0x0, 0x0, 0x0)
C:/Program Files/Go/src/runtime/cgocall.go:232 +0x106
runtime.cgocallbackg(0x67315640, 0x108efee9c0, 0x0)
&lt;autogenerated&gt;:1 +0x36
runtime.cgocallback(0x0, 0x0, 0x0)
C:/Program Files/Go/src/runtime/asm_amd64.s:915 +0xd7
runtime.goexit()
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:

package main

import (
	&quot;C&quot;
	&quot;strconv&quot;
)

//export PrintAlg
func PrintAlg(debug bool) string {
	var b200 int = 0
	var b300 int = 0
	var b400 int = 0
	var x string = &quot;A&quot;
	if debug == true {
		// extra
	} else if debug == false {
		for i := 1; i &lt;= 100; i++ {
			if i%4 == 0 &amp;&amp; i%3 == 0 {
				b200++
				b300++
				b400++
			} else if i%4 == 0 &amp;&amp; !(i%3 == 0) {
				b400++
				b200++
			} else if i%2 == 0 &amp;&amp; i%3 == 0 &amp;&amp; !(i%4 == 0) {
				b200++
				b300++
			} else if i%3 == 0 &amp;&amp; !(i%2 == 0) &amp;&amp; !(i%4 == 0) {
				b300++
			} else if i%2 == 0 &amp;&amp; !(i%3 == 0) &amp;&amp; !(i%4 == 0) {
				b200++
			} else if i%2 == 0 &amp;&amp; i%3 == 0 &amp;&amp; i%4 == 0 {
				b200++
				b300++
				b400++
			}
		}
		x = strconv.Itoa(b200) + &quot; &quot; + strconv.Itoa(b300) + &quot; &quot; + strconv.Itoa(b400)
	}
	return x
}

func main() {

}


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

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

what can i do for fixing this error?

答案1

得分: 1

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

type stringStruct struct {
    str unsafe.Pointer
    len int
}

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

panic: runtime error: cgo result has Go pointer

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

在Go中,可以这样编写:

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

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



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

recap.go:

package main

import (
    "C"
    "strconv"
)

//export PrintAlg
func PrintAlg(debug bool) *C.char {
    var b200 int = 0
    var b300 int = 0
    var b400 int = 0
    var x string = "A"
    if debug == true {
        // extra
    } else if debug == false {
        for i := 1; i <= 100; i++ {
            if i%4 == 0 && i%3 == 0 {
                b200++
                b300++
                b400++
            } else if i%4 == 0 && !(i%3 == 0) {
                b400++
                b200++
            } else if i%2 == 0 && i%3 == 0 && !(i%4 == 0) {
                b200++
                b300++
            } else if i%3 == 0 && !(i%2 == 0) && !(i%4 == 0) {
                b300++
            } else if i%2 == 0 && !(i%3 == 0) && !(i%4 == 0) {
                b200++
            } else if i%2 == 0 && i%3 == 0 && i%4 == 0 {
                b200++
                b300++
                b400++
            }
        }
        x = strconv.Itoa(b200) + " " + strconv.Itoa(b300) + " " + strconv.Itoa(b400)
    }
    return C.CString(x)
}

func main() {}

recap.py:

import ctypes
recap = ctypes.cdll.LoadLibrary('./_recap.so')
printAlg = recap.PrintAlg
printAlg.argtypes = [ctypes.c_bool]
printAlg.restype = ctypes.c_void_p
free = recap.free
free.argtypes = [ctypes.c_void_p]
px = printAlg(False)
x = ctypes.string_at(px).decode('utf-8')
free(px)
print(x)
英文:

The Go runtime implementation of a string is

type stringStruct struct {
str unsafe.Pointer
len int
}

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.

panic: runtime error: cgo result has Go pointer

Read the cgo documentation, especially Passing_pointers, for details.

In Go, write

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

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



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

recap.go:

package main
import (
&quot;C&quot;
&quot;strconv&quot;
)
//export PrintAlg
func PrintAlg(debug bool) *C.char {
var b200 int = 0
var b300 int = 0
var b400 int = 0
var x string = &quot;A&quot;
if debug == true {
// extra
} else if debug == false {
for i := 1; i &lt;= 100; i++ {
if i%4 == 0 &amp;&amp; i%3 == 0 {
b200++
b300++
b400++
} else if i%4 == 0 &amp;&amp; !(i%3 == 0) {
b400++
b200++
} else if i%2 == 0 &amp;&amp; i%3 == 0 &amp;&amp; !(i%4 == 0) {
b200++
b300++
} else if i%3 == 0 &amp;&amp; !(i%2 == 0) &amp;&amp; !(i%4 == 0) {
b300++
} else if i%2 == 0 &amp;&amp; !(i%3 == 0) &amp;&amp; !(i%4 == 0) {
b200++
} else if i%2 == 0 &amp;&amp; i%3 == 0 &amp;&amp; i%4 == 0 {
b200++
b300++
b400++
}
}
x = strconv.Itoa(b200) + &quot; &quot; + strconv.Itoa(b300) + &quot; &quot; + strconv.Itoa(b400)
}
return C.CString(x)
}
func main() {}

recap.py:

import ctypes
recap = ctypes.cdll.LoadLibrary(&#39;./_recap.so&#39;)
printAlg = recap.PrintAlg
printAlg.argtypes = [ctypes.c_bool]
printAlg.restype = ctypes.c_void_p
free = recap.free
free.argtypes = [ctypes.c_void_p]
px = printAlg(False)
x = ctypes.string_at(px).decode(&#39;utf-8&#39;)
free(px)
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:

确定