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

Chr*_*end 2 go 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() {}
Run Code Online (Sandbox Code Playgroud)

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

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

我正在建立这个如下:

转到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 ++中自动生成的char数组。当我尝试返回k.Key时,它会抛出一个字符串。是否可以转换Go字符串或在出口装饰中添加一些符号以使其起作用?

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

谢谢您的时间和解释。

Jim*_*imB 5

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

//export GetKey
func GetKey() *C.char {
    theKey := lookupKey()
    return C.CString(theKey)
}
Run Code Online (Sandbox Code Playgroud)

该函数的返回值必须在C代码中显式释放。

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

func GetKey(buff *C.char, n int) int
Run Code Online (Sandbox Code Playgroud)

如果可以分配内存但不想处理C字符串,则可以将缓冲区插入指针并返回大小。

func GetKey(buff **C.char) int
Run Code Online (Sandbox Code Playgroud)