Cgo:如何将双数组从C返回到Go

时间:2016-03-19 07:01:39

标签: c pointers memory go cgo

我有一个像这样的C函数

double* c_func(int n_rows) {
  double result[n_rows];
  for (int i = 0; i < n_rows; ++i) {
    result[i] = (double)i;
  }
  return result;
}

我使用此Go函数来处理C double:

// convert C double pointer to float64 slice ...
func doubleToFloats(in *C.double, length int) []float64 {
    out := make([]float64, length, length)

    start := unsafe.Pointer(in)
    size := unsafe.Sizeof(C.double(0))
    for i := 0; i < length; i++ {
        val := *(*C.double)(unsafe.Pointer(uintptr(start) + size*uintptr(i)))
        out[i] = float64(val)
    }
    return out
}

这有时可行,但有时不行。当它不起作用时,它会返回如下内容:

[0 1 2 3 4 5 6 7 8 9 10 2.53e-321 3.32018606e-316 4.24664374149e-312 4.24399158193e-312 1.1383e-320 3.31882387e-316 3.71924634e-316 3.31885594e-316 3.71924634e-316 5e-324 0 4.6950308e-316 4.24664374149e-312 3.7175681e-316 3.3200616e-316]

对我来说看起来有点内存问题......

我不确定这是否是从Go中的C处理返回的双数组的正确方法。如果是,如何解决问题(偶尔发生)。如果不是,从C处理返回的双数组的正确方法是什么?

感谢。

2 个答案:

答案 0 :(得分:0)

在C中,你返回的指针将是陈旧的。你需要像double * result = calloc(sizeof(double),nrows)这样分配表 - 这也需要一种释放内存的方法。

答案 1 :(得分:-1)

好的,所以我找到了一种简单的方法来实现这一点。

我们首先使用calloc为数组分配内存:

double* c_func(int n_rows) {
    double* result;
    result = calloc(n_rows, sizeof(double));
    for (int i = 0; i < n_rows; ++i) {
        result[i] = (double)i;
    }
    return result;
}

之后,我们只需将数据转换为Go中的正确类型。诀窍是使用C.free释放从C端分配的内存。

// convert C double pointer to float64 slice ...
func doubleToFloats(in *C.double, size int) []float64 {
    defer C.free(unsafe.Pointer(in))
    out := (*[1 << 30]float64)(unsafe.Pointer(in))[:size:size]
    return out
}