Cgo:如何 return 从 C 到 Go 的双数组
Cgo: How to return double array from C to Go
我得到了这样一个 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
}
这有时有效但有时无效。当它不起作用时,它 return 像这样:
[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 的 returned 双精度数组的正确方法。如果是,如何解决问题(偶尔会发生)。如果不是,那么从 C 处理 returned double 数组的正确方法是什么?
谢谢。
在 C 中,您 return 的那个指针将会过时。您需要像 double *result = calloc(sizeof(double), nrows) 一样分配 table --- 这还需要有一种释放内存的方法。
好的,所以我想出了一个简单的方法来实现这一点。
我们先用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
}
我得到了这样一个 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
}
这有时有效但有时无效。当它不起作用时,它 return 像这样:
[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 的 returned 双精度数组的正确方法。如果是,如何解决问题(偶尔会发生)。如果不是,那么从 C 处理 returned double 数组的正确方法是什么?
谢谢。
在 C 中,您 return 的那个指针将会过时。您需要像 double *result = calloc(sizeof(double), nrows) 一样分配 table --- 这还需要有一种释放内存的方法。
好的,所以我想出了一个简单的方法来实现这一点。
我们先用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
}