如何将JSON中的字符串返回给C调用方(Golang CGO)? 我试图在GO中开发一个程序,它将由C++程序调用。围棋如下所示: package main import ( "C" "encoding/json" "log" ) type keydata struct { Key string `json:"key"` Error string `json:"Error"` } func lookupKey() string { //simplified to remove the call to web service body := "{\"key\": \"blahblah\", \"Error\": \"\"}" k := keydata{} err := json.Unmarshal([]byte(body), &k) if err != nil { log.Fatal(err) } return k.Key } //export GetKey func GetKey() string { theKey := lookupKey() return theKey } func main() {} 如果我用一些硬编码值替换返回K.KEY语句,那么所有的工作都很好,C或C++可以调用导出的GEKEY函数。当我试图从k.Key返回解码后的JSON字符串,甚至只是从名为body的变量返回字符串时,我收到一个错误:

如何将JSON中的字符串返回给C调用方(Golang CGO)? 我试图在GO中开发一个程序,它将由C++程序调用。围棋如下所示: package main import ( "C" "encoding/json" "log" ) type keydata struct { Key string `json:"key"` Error string `json:"Error"` } func lookupKey() string { //simplified to remove the call to web service body := "{\"key\": \"blahblah\", \"Error\": \"\"}" k := keydata{} err := json.Unmarshal([]byte(body), &k) if err != nil { log.Fatal(err) } return k.Key } //export GetKey func GetKey() string { theKey := lookupKey() return theKey } func main() {} 如果我用一些硬编码值替换返回K.KEY语句,那么所有的工作都很好,C或C++可以调用导出的GEKEY函数。当我试图从k.Key返回解码后的JSON字符串,甚至只是从名为body的变量返回字符串时,我收到一个错误:,go,cgo,Go,Cgo,运行时错误:cgo结果具有Go指针 goroutine 17[正在运行,锁定到线程] 我将按如下方式构建此功能: go build-buildmode=c-archive example.go C++是按照以下方式构建的: g++-pthread test.cpp示例.a-o测试 在不引起恐慌性错误的情况下,我错过了什么?我正在四处寻找答案,但还没有解决这个问题 @JimB&@Jsor,非常感谢您的回复。返回一个*C.char肯定有效。不过,我很好奇,当我在自动生成的头文件中以Go字符串的形式

运行时错误:cgo结果具有Go指针 goroutine 17[正在运行,锁定到线程]

我将按如下方式构建此功能:

go build-buildmode=c-archive example.go

C++是按照以下方式构建的:

g++-pthread test.cpp示例.a-o测试

在不引起恐慌性错误的情况下,我错过了什么?我正在四处寻找答案,但还没有解决这个问题

@JimB&@Jsor,非常感谢您的回复。返回一个*C.char肯定有效。不过,我很好奇,当我在自动生成的头文件中以Go字符串的形式返回它时,Go实际上创建并传递了一个名为GoString的C结构,其中包含一个名为p的字符数组和名为n的长度。只要我通过一个硬编码字符串而不是K.KEY,它实际上是可以工作的,我可以在C++中查询自动生成的字符数组。当我试图返回k.Key时,它抛出了一个异常字符串。是否有可能铸造围棋字符串或向导出装饰添加一些符号以使其工作

我当然可以返回C.CString字符数组并使其正常工作-谢谢!我还想了解为什么它在返回硬编码字符串时有效,而不是在我发布的示例中


感谢您的时间和解释。

您需要使用
C.CString
将Go字符串转换为原始指针,再转换为C字符串。请注意,C字符串不是垃圾收集的,必须由您在程序的其他地方释放


这将使返回类型
*C.char
对C来说应该是一个
char
数组。返回缓冲区长度也是您的责任(是否编写单独的函数或C结构取决于您)。

您不能将Go
字符串返回到C函数。如果需要C字符串,可以使用
C.CString
函数创建一个并返回
*C.char

//export GetKey
func GetKey() *C.char {
    theKey := lookupKey()
    return C.CString(theKey)
}
此函数的返回值必须在C代码中显式释放

如果释放分配的缓冲区不方便,则通常会填充调用者提供的缓冲区:

func GetKey(buff *C.char, n int) int
如果可以分配内存但不想处理C字符串,可以将缓冲区插入指针并返回大小

func GetKey(buff **C.char) int

(仅供参考,@只在注释中提及工作)您不能从C安全地使用GoString,因为它包含一个指向Go中分配的内存的指针。cgocheck没有注意到使用字符串文字这一事实。@JimB,谢谢你的提示和解释。