我正在尝试在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数组并使它工作-谢谢!我只是想了解为什么返回硬编码字符串时它起作用,而不是在我发布的示例中。
谢谢您的时间和解释。
您不能将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)