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 關注
- 163 瀏覽
添加回答
舉報