2 回答
TA贡献1921条经验 获得超9个赞
在 Go 中,[]T
它并不像你想象的那样:它不是一个数组,而是一个切片。
切片由struct
三个字段组成:length int
,capacity int
以及指向基础(支持)数组的第一个元素的指针。
相反,在 C 和 C++ 中,a直接T[]
是指向内存块的指针(其迭代恰好以字节块的形式完成)。sizeof(T)
因此你char *pairs[][2]
是
指向类型为两个元素的内存块的指针
char*[]
,其中每个元素都是指向另一个包含未知数量的类型元素的数组的指针
char*
。
…你的 Go[][]*C.char
是一个切片的切片(即struct
- 类型的切片头,而不是指针)。
你可能需要这样的东西:
var argv = make([][2]*C.char, len(keypairs))
i := 0
for key, val := range keypairs {
var argv2 = new([2]*C.char)
argv2[0], argv2[1] := C.CString(key), C.CString(val)
argv[i] = argv2
i++
}
C.writeKeyValuePairs(&argv[0])
这里我们分配一个数组切片(长度为 2)。在调用 C 端时,您可以正确获取封闭数组的第一个元素的地址,因此在顶层有一个切片就可以了。
这段代码的问题是,您没有传递数据的长度argv,writeKeyValuePairs也没有在该数组的末尾使用哨兵值,但我希望您刚刚从示例中删除了该位。
C.CString我也无法理解为什么你立即释放分配的内存。手册说:
// Go string to C string
// The C string is allocated in the C heap using malloc.
// It is the caller's responsibility to arrange for it to be
// freed, such as by calling C.free (be sure to include stdlib.h
// if C.free is needed).
func C.CString(string) *C.char
因此,在指向键/值对的指针被分配给相应的数组条目对之后,您似乎立即释放了键/值对的内存块。我怀疑这是一个错误:释放必须在 C 函数完成执行后进行。
TA贡献1876条经验 获得超5个赞
我在 Go 中有一个 map[string]string,我希望在 C++ 中迭代这个键/值对。
用你的例子,
package main
/*
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
bool writeKeyValuePairs(char *pairs[][2], size_t size) {
for (size_t i = 0; i < size; i++ ) {
if (fprintf(stdout, "%s: %s\n", pairs[i][0], pairs[i][1]) < 0) {
return false;
}
}
return true;
}
*/
import "C"
import (
"fmt"
"os"
"unsafe"
)
func allocCPairs(m map[string]string) (*[2]*C.char, C.size_t) {
kv := make([][2]*C.char, 0, len(m)+1)
for k, v := range m {
kv = append(kv, [2]*C.char{0: C.CString(k), 1: C.CString(v)})
}
return &kv[:cap(kv)][0], C.size_t(len(kv))
}
func freeCPairs(cPairs *[2]*C.char, size C.size_t) {
gPairs := (*[1 << 30][2]*C.char)(unsafe.Pointer(cPairs))[:size]
for _, pair := range gPairs {
for _, p := range pair {
C.free(unsafe.Pointer(p))
}
}
}
func writeKeyValuePairs(m map[string]string) error {
cPairs, size := allocCPairs(m)
defer freeCPairs(cPairs, size)
rv := C.writeKeyValuePairs(cPairs, size)
if !rv {
return fmt.Errorf("writeKeyValuePairs: write error")
}
return nil
}
func main() {
m := map[string]string{
"K1": "V1",
"K2": "V2",
// ...
"Kn": "Vn",
}
fmt.Println(m)
err := writeKeyValuePairs(m)
if err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
}
输出:
map[K1:V1 K2:V2 Kn:Vn]
K1: V1
K2: V2
Kn: Vn
- 2 回答
- 0 关注
- 124 浏览
添加回答
举报