如何从C语言返回双精度数组给Go语言?

huangapple go评论136阅读模式
英文:

Cgo: How to return double array from C to Go

问题

我有一个像这样的C函数:

  1. double* c_func(int n_rows) {
  2. double result[n_rows];
  3. for (int i = 0; i < n_rows; ++i) {
  4. result[i] = (double)i;
  5. }
  6. return result;
  7. }

我使用以下Go函数来处理C中的double:

  1. // convert C double pointer to float64 slice ...
  2. func doubleToFloats(in *C.double, length int) []float64 {
  3. out := make([]float64, length, length)
  4. start := unsafe.Pointer(in)
  5. size := unsafe.Sizeof(C.double(0))
  6. for i := 0; i < length; i++ {
  7. val := *(*C.double)(unsafe.Pointer(uintptr(start) + size*uintptr(i)))
  8. out[i] = float64(val)
  9. }
  10. return out
  11. }

有时它可以正常工作,但有时不行。当它不工作时,它会返回类似以下的内容:

  1. [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]

这看起来像是内存问题...

我不确定这是否是正确处理从C返回的double数组的方法。如果是,如何解决这个问题(偶尔出现)?如果不是,正确处理从C返回的double数组的方法是什么?

谢谢。

英文:

I got a C function like this

  1. double* c_func(int n_rows) {
  2. double result[n_rows];
  3. for (int i = 0; i &lt; n_rows; ++i) {
  4. result[i] = (double)i;
  5. }
  6. return result;
  7. }

And I use this Go function to process the C double:

  1. // convert C double pointer to float64 slice ...
  2. func doubleToFloats(in *C.double, length int) []float64 {
  3. out := make([]float64, length, length)
  4. start := unsafe.Pointer(in)
  5. size := unsafe.Sizeof(C.double(0))
  6. for i := 0; i &lt; length; i++ {
  7. val := *(*C.double)(unsafe.Pointer(uintptr(start) + size*uintptr(i)))
  8. out[i] = float64(val)
  9. }
  10. return out
  11. }

This sometimes works but sometimes not. When it not works, it return something like this:

  1. [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]

which looks like somewhat memory issue to me...

I'm not sure if this is the correct way to handle returned double array from C in Go. If yes, how to fix the problem (which occurs ocassionally). If no, what is the correct way to handle returned double array from C?

Thanks.

答案1

得分: 0

在C语言中,你返回的指针将会变得无效。你需要像这样分配内存空间:double *result = calloc(sizeof(double), nrows),同时也需要有一种方法来释放内存。

英文:

In C, that pointer you return is going to be stale. You would need to allocate the table like double *result = calloc(sizeof(double), nrows) --- which would require also have a way to free the memory.

答案2

得分: -1

好的,以下是翻译好的内容:

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

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

  1. double* c_func(int n_rows) {
  2. double* result;
  3. result = calloc(n_rows, sizeof(double));
  4. for (int i = 0; i < n_rows; ++i) {
  5. result[i] = (double)i;
  6. }
  7. return result;
  8. }

之后,我们只需将数据转换为Go中的适当类型。关键是使用C.free来释放从C端分配的内存。

  1. // 将C的double指针转换为float64切片...
  2. func doubleToFloats(in *C.double, size int) []float64 {
  3. defer C.free(unsafe.Pointer(in))
  4. out := (*[1 << 30]float64)(unsafe.Pointer(in))[:size:size]
  5. return out
  6. }
英文:

OK, so I figured out a simple way to achieve this.

We first use calloc to allocate memory for the array:

  1. double* c_func(int n_rows) {
  2. double* result;
  3. result = calloc(n_rows, sizeof(double));
  4. for (int i = 0; i &lt; n_rows; ++i) {
  5. result[i] = (double)i;
  6. }
  7. return result;
  8. }

and after that, we simply convert the data into proper type in Go. The trick is to use C.free to free the memory allocated from C side.

  1. // convert C double pointer to float64 slice ...
  2. func doubleToFloats(in *C.double, size int) []float64 {
  3. defer C.free(unsafe.Pointer(in))
  4. out := (*[1 &lt;&lt; 30]float64)(unsafe.Pointer(in))[:size:size]
  5. return out
  6. }

huangapple
  • 本文由 发表于 2016年3月19日 15:01:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/36098875.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定