2 回答

TA貢獻(xiàn)1921條經(jīng)驗(yàn) 獲得超9個(gè)贊
在 Go 中,[]T
它并不像你想象的那樣:它不是一個(gè)數(shù)組,而是一個(gè)切片。
切片由struct
三個(gè)字段組成:length int
,capacity int
以及指向基礎(chǔ)(支持)數(shù)組的第一個(gè)元素的指針。
相反,在 C 和 C++ 中,a直接T[]
是指向內(nèi)存塊的指針(其迭代恰好以字節(jié)塊的形式完成)。sizeof(T)
因此你char *pairs[][2]
是
指向類型為兩個(gè)元素的內(nèi)存塊的指針
char*[]
,其中每個(gè)元素都是指向另一個(gè)包含未知數(shù)量的類型元素的數(shù)組的指針
char*
。
…你的 Go[][]*C.char
是一個(gè)切片的切片(即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])
這里我們分配一個(gè)數(shù)組切片(長(zhǎng)度為 2)。在調(diào)用 C 端時(shí),您可以正確獲取封閉數(shù)組的第一個(gè)元素的地址,因此在頂層有一個(gè)切片就可以了。
這段代碼的問題是,您沒有傳遞數(shù)據(jù)的長(zhǎng)度argv,writeKeyValuePairs也沒有在該數(shù)組的末尾使用哨兵值,但我希望您剛剛從示例中刪除了該位。
C.CString我也無法理解為什么你立即釋放分配的內(nèi)存。手冊(cè)說:
// 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
因此,在指向鍵/值對(duì)的指針被分配給相應(yīng)的數(shù)組條目對(duì)之后,您似乎立即釋放了鍵/值對(duì)的內(nèi)存塊。我懷疑這是一個(gè)錯(cuò)誤:釋放必須在 C 函數(shù)完成執(zhí)行后進(jìn)行。

TA貢獻(xiàn)1876條經(jīng)驗(yàn) 獲得超5個(gè)贊
我在 Go 中有一個(gè) map[string]string,我希望在 C++ 中迭代這個(gè)鍵/值對(duì)。
用你的例子,
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 關(guān)注
- 159 瀏覽
添加回答
舉報(bào)