首页 > 解决方案 > CGO:将 Go 字节数组转换为 C char* 并返回,字节数组中出现空终止符

问题描述

简要背景:我正在尝试为我的公司从 uint64->[]byte 创建一个 cgo 缓存。map[uint64][]byte由于垃圾收集器,Golang会产生相当大的延迟,因为 []byte 被认为是一个指针。因此,我想尝试使用 CGO 来避免这个问题。我目前正在实施一个C++ unordered_map<unsigned long long, char*>来处理这个问题。我设法让 C++ 包装器工作,但我面临一个重大问题。

目前,我正在使用转换我的 Go 字节数组

b := []byte{1,0,3,32,2,2,2,2}
str := C.String(b)
bb := []byte(C.GoString(str))

然而,事实证明我的 bb 是[]byte{1}。字节数组中的 0 被视为'/0',因此缩短了字符串。此外,当我删除条目时,它似乎会导致内存不足的问题

delete (map->find(key))->second. 我怀疑这是因为第一个字符之后的字符'/0'没有被释放。我不知道该怎么做。就个人而言,我是 CGO 的新手,所以在这个项目之前我从未使用过它,所以任何帮助都将不胜感激。

标签: gomemoryc-stringscgo

解决方案


有两个问题:

  • 使用C.CBytes,不使用C.CString

    请在使用前完整阅读cgo内容。

  • C.C*分配(C.CString并执行此操作)的函数在C.CBytes内部malloc()从链接的libc库中调用以获取目标内存块,并且您应该最终调用C.Free()它们(调用libc's free()),如文档所述。

    AFAIK,C++ 编译器决不是必须使用libc'smalloc()free()实现newand delete,所以调用函数delete的结果C.C*肯定会导致灾难。

    IMO,解决这个问题的最简单方法是从 C++ 端导出一个“构造函数”函数:类似于

    extern "C" {
        char* clone(char *src, size_t len);
    }
    

    len…这将 1)使用最适合 C++ 的任何方法分配长度的内存块;2)从中复制len字节src;3) 退货。

    然后,您可以从 Go 端C.clone(&b[0], len(b))调用它——就像一天结束一样:C++ 端可以自由调用delete结果。


推荐阅读