dongshan4316 2017-03-01 11:29
浏览 237
已采纳

如何在Go中将指向切片的指针传递给C函数

Background: using cgo to call C functions from Golang.

I want to use a C function which has this signature: 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. The value of count is the length of strs; strs is an array of string; 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 C.f((*C.int)(&count)); pass []string by using []*C.char. Sample code is like this:

/*
#include <stdio.h>
int f(int *c, char **str) {
    int i;
    printf("%d
", *c);
    for (i = 0; i < *c; i++) {
        printf("%s
", 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).

This is to say: what I actually want is to enable the modification to the string array (e.g. resize) in C and turn it back to a Go string slice so I can still use it in Go.

How to do this? I've searched and experimented for a while but with no luck.

  • 写回答

1条回答 默认 最新

  • dpnw86361 2017-03-01 14:05
    关注

    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)

    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.

    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)))
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 ros的rviz仿真机器人
  • ¥15 关于#linux#的问题(输入输出错误):出现这个界面接着我重新装系统,又让修电脑的师傅帮我扫描硬盘(没有问题)用着用着又卡死(相关搜索:固态硬盘)
  • ¥15 cv::resize不同线程时间不同
  • ¥15 web课程,怎么做啊😭没好好听课 根本不知道怎么下手
  • ¥15 做一个关于单片机的比较难的代码,然后搞一个PPT进行解释
  • ¥15 python提取.csv文件中的链接会经常出现爬取失败
  • ¥15 数据结构中的数组地址问题
  • ¥15 maya的mel里,怎样先选择模型A,然后利用mel脚本自动选择有相同名字的模型B呢。
  • ¥15 Python题,根本不会啊
  • ¥15 会会信号与系统和python的来