如何在go中将指向切片的指针传递给C函数
How to pass pointer to slice to C function in go
背景:使用cgo调用Golang中的C函数
我想使用具有此签名的 C 函数:int f(int *count, char ***strs)
。
它将修改 count
和 strs
的数据,这就是它使用指向它们的指针的原因。
count
的值是strs
的长度; strs
是一个字符串数组; return 值只是一个(布尔值)指示器,它表明是否存在错误。
在golang中,我使用C.f((*C.int)(&count))
可以成功传递和修改count
;使用 []*C.char
传递 []string
。示例代码是这样的:
/*
#include <stdio.h>
int f(int *c, char **str) {
int i;
printf("%d\n", *c);
for (i = 0; i < *c; i++) {
printf("%s\n", str[i]);
}
*c = (*c) + 1;
return 1;
}
*/
import "C"
func go_f(strs []string) int {
count := len(strs)
c_count := C.int(count)
c_strs := make([]*C.char, count)
for index, value := range strs {
c_strs[index] = C.CString(value)
defer C.free(unsafe.Pointer(c_strs[index]))
}
err := C.f(&c_argc, (**C.char)(&c_argv[0]))
return int(err)
}
如您所见,C 函数目前是 int f(int *c, char **str)
,但我想要的是 int f(int *c, char ***str)
。
这就是说:我真正想要的是在C中启用对字符串数组的修改(例如调整大小)并将其转回Go字符串切片以便我仍然可以在Go中使用它。
如何做到这一点?我已经搜索和试验了一段时间,但没有成功。
Go slice 是在 Go 中分配的,并且是与 C 数组不同的数据结构,所以你不能将它传递给 C 函数(cgo 也会阻止你这样做,因为一个 slice 包含一个 Go指针)
您需要在 C 中分配数组以便在 C 中操作数组。就像 C.CString 一样,您还需要跟踪释放外部数组的位置,特别是如果 C 函数可能可能分配一个新数组。
cArray := C.malloc(C.size_t(c_count) * C.size_t(unsafe.Sizeof(uintptr(0))))
// convert the C array to a Go Array so we can index it
a := (*[1<<30 - 1]*C.char)(cArray)
for index, value := range strs {
a[index] = C.CString(value)
}
err := C.f(&c_count, (***C.char)(unsafe.Pointer(&cArray)))
背景:使用cgo调用Golang中的C函数
我想使用具有此签名的 C 函数:int f(int *count, char ***strs)
。
它将修改 count
和 strs
的数据,这就是它使用指向它们的指针的原因。
count
的值是strs
的长度; strs
是一个字符串数组; return 值只是一个(布尔值)指示器,它表明是否存在错误。
在golang中,我使用C.f((*C.int)(&count))
可以成功传递和修改count
;使用 []*C.char
传递 []string
。示例代码是这样的:
/*
#include <stdio.h>
int f(int *c, char **str) {
int i;
printf("%d\n", *c);
for (i = 0; i < *c; i++) {
printf("%s\n", str[i]);
}
*c = (*c) + 1;
return 1;
}
*/
import "C"
func go_f(strs []string) int {
count := len(strs)
c_count := C.int(count)
c_strs := make([]*C.char, count)
for index, value := range strs {
c_strs[index] = C.CString(value)
defer C.free(unsafe.Pointer(c_strs[index]))
}
err := C.f(&c_argc, (**C.char)(&c_argv[0]))
return int(err)
}
如您所见,C 函数目前是 int f(int *c, char **str)
,但我想要的是 int f(int *c, char ***str)
。
这就是说:我真正想要的是在C中启用对字符串数组的修改(例如调整大小)并将其转回Go字符串切片以便我仍然可以在Go中使用它。
如何做到这一点?我已经搜索和试验了一段时间,但没有成功。
Go slice 是在 Go 中分配的,并且是与 C 数组不同的数据结构,所以你不能将它传递给 C 函数(cgo 也会阻止你这样做,因为一个 slice 包含一个 Go指针)
您需要在 C 中分配数组以便在 C 中操作数组。就像 C.CString 一样,您还需要跟踪释放外部数组的位置,特别是如果 C 函数可能可能分配一个新数组。
cArray := C.malloc(C.size_t(c_count) * C.size_t(unsafe.Sizeof(uintptr(0))))
// convert the C array to a Go Array so we can index it
a := (*[1<<30 - 1]*C.char)(cArray)
for index, value := range strs {
a[index] = C.CString(value)
}
err := C.f(&c_count, (***C.char)(unsafe.Pointer(&cArray)))