【发布时间】:2020-11-29 16:18:36
【问题描述】:
我正在用 Go (c-shared) 编写一个共享对象,它将从 python 加载和运行。一切正常,直到 Go 代码需要返回错误。我正在使用 error.Error() 将错误转换为字符串,但是当尝试将其返回给 python 时,cgo 正在命中:
panic: runtime error: cgo result has Go pointer
这很奇怪,因为这是一个字符串,而不是一个指针。我知道通过共享对象导出函数返回 go 字符串没有问题,因为我在其他几个地方这样做没有任何问题。
Go 代码如下所示:
package main
import "C"
//export MyFunction
func MyFunction() string {
err := CallSomethingInGo()
if err != nil {
return err.Error()
}
return ""
}
func main() {}
使用 buildmode=c-shared 将 go 代码编译为 .so,然后在 python 代码中,我有这样的内容:
from ctypes import *
lib = cdll.LoadLibrary("./mygocode.so")
class GoString(Structure):
_fields_ = [("p", c_char_p),("n", c_longlong)]
theFunction = lib.MyFunction
theFunction.restype = GoString
err = theFunction()
当最后一行执行并且 golang 代码返回 NO 错误时,一切都很好并且可以正常工作!但是,如果 golang 代码尝试返回错误(例如 CallSomethingInGo 失败并返回 err),那么 python 代码将失败并显示:
panic: runtime error: cgo result has Go pointer
我已经尝试从 go 手动返回字符串到 python 并且它工作正常,但是尝试返回 error.Error() (根据我的理解应该是一个字符串)失败。将错误的字符串表示形式返回给python的正确方法是什么?
还有一条信息——来自 golang,我做了一个 printf("%T", err) ,我看到错误的类型是:
*os.PathError
我也做了 printf("%T", err.Error()) 并确认 err.Error() 返回的类型是 'string' 所以我仍然不确定为什么这不起作用。
对我来说甚至更陌生...我尝试修改 go 函数,如下所示进行测试,这段代码工作正常并将“test”作为字符串返回给 python...
//export MyFunction
func MyFunction() string {
err := CallSomethingInGo()
if err != nil {
// test
x := errors.New("test")
return x.Error()
}
return ""
}
我很困惑!该测试如何工作,而不是 err.Error() ?
【问题讨论】:
-
Python 并不恐慌。 Go 运行时就是这样做的。不允许将 Go 字符串(也不是任何 Go 指针)返回到 C 代码中。仔细阅读 cgo 文档的this section。
-
我可以毫无问题地返回一个 go 字符串 - 请参阅我后面的示例,它们工作正常。我还在已导出的多个其他函数中返回字符串(从不出错)。这似乎不是这里的问题。
-
您可以将 Go 字符串返回给 Go 代码。您不能将一返回给 C 代码。运行时是否会捕获这个错误完全是另一回事,但你不能这样做。
标签: python string go error-handling cgo