如何 return 从 JSON 到 C 调用者(Golang CGO)的字符串?

How to return a string from JSON to a C caller (Golang CGO)?

我正在尝试在 Go 中开发一个将由 C++ 程序调用的例程。 Go 如下所示:

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() {}

如果我用一些硬编码值替换 return k.Key 语句,一切正常,C 或 C++ 可以调用导出的 GetKey 函数。当我尝试 return 来自 k.Key 的解码 JSON 字符串,甚至只是 return 来自名为 body 的变量的字符串时 - 我收到错误消息:

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

我按如下方式构建:

go build -buildmode=c-archive example.go

C++ 构建如下:

g++ -pthread test.cpp example.a -o 测试

我缺少什么才能在不引发恐慌错误的情况下完成这项工作?我正在四处寻找答案,但尚未解决这个问题。

@JimB 和@Jsor,非常感谢您的回复。返回 *C.char 当然有效。不过,我想知道,当我 return 它作为自动生成的头文件中幕后的 Go 字符串时,Go 实际上创建并传递了一个名为 GoString 的 C 结构,其中包含一个名为 p 的字符数组和名为 n 的长度.只要我传递一个硬编码字符串而不是 k.Key 它就可以正常工作,我可以在 C++ 中查询自动生成的 char 数组。当我尝试 return k.Key 一个字符串时,它会抛出该异常。是否可以转换 Go 字符串或向导出装饰添加一些符号以使其工作?

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

谢谢你们的时间和解释。

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

这将使 return 类型 *C.char 应该作为 char 数组对 C 可见。 return 缓冲区长度也是您的责任(是否编写单独的函数或 C 结构来执行此操作取决于您)。

您不能 return Go string 到 C 函数。如果你想要一个 C 字符串,你可以使用 C.CString 函数创建一个 return 一个 *C.char

//export GetKey
func GetKey() *C.char {
    theKey := lookupKey()
    return C.CString(theKey)
}

此函数 的 return 值必须 在 C 代码中显式释放。

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

func GetKey(buff *C.char, n int) int

如果你可以分配内存但不想处理 C 字符串,你可以将缓冲区插入一个指针和 return 大小。

func GetKey(buff **C.char) int