简体   繁体   English

如何在go中将指针传递给切片到C函数

[英]How to pass pointer to slice to C function in go

Background: using cgo to call C functions from Golang. 背景:使用cgo从Golang调用C函数。

I want to use a C function which has this signature: int f(int *count, char ***strs) . 我想使用具有此签名的C函数: int f(int *count, char ***strs) It will modify the data of count and strs , which is the reason why it uses pointer to them. 它将修改countstrs的数据,这就是它使用指针的原因。 The value of count is the length of strs ; count的值是strs的长度; strs is an array of string; strs是一个字符串数组; the return value is simply an (boolean) indicator which states whether there is an error or not. 返回值只是一个(布尔)指示符,指示是否存在错误。

In golang, I can successfully pass and modify count by using Cf((*C.int)(&count)) ; 在golang中,我可以通过使用Cf((*C.int)(&count))成功传递和修改count ; pass []string by using []*C.char . 使用[]*C.char传递[]string Sample code is like this: 示例代码如下:

/*
#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)
}

As you can see, the C function is currently int f(int *c, char **str) , but what I'd like is int f(int *c, char ***str) . 如你所见,C函数目前是int f(int *c, char **str) ,但我想要的是int f(int *c, char ***str)

This is to say: what I actually want is to enable the modification to the string array (eg resize) in C and turn it back to a Go string slice so I can still use it in Go. 这就是说:我真正想要的是在C中启用对字符串数组的修改(例如调整大小)并将其转回Go字符串切片,这样我仍然可以在Go中使用它。

How to do this? 这该怎么做? I've searched and experimented for a while but with no luck. 我已经搜索并试验了一段时间,但没有运气。

A Go slice is both allocated in Go, and a different data structure than a C array, so you can't pass it to a C function (cgo will also prevent you from doing this because a slice contains a Go pointer) Go切片既在Go中分配,又在C数组中分配不同的数据结构,因此您无法将其传递给C函数(cgo也会阻止您执行此操作,因为切片包含Go指针)

You need to allocate the array in C in order to manipulate the array in C. Just like with C.CString, you will also need to track where to free the outer array, especially if the C function may possibly allocate a new array. 您需要在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)))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM