CGO从C中获取一个[][]float32类型的值

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

CGO getting a [][]float32 from C ** float

问题

我正在尝试使用一个具有C兼容头文件的C++库中的函数,它希望我传入一个4x4矩阵以供其填充。

我的Go函数定义如下:

func GetMatrix(matrix []float32)

而C头文件中的定义如下:

void getMatrix(const float **matrix)

我尝试使用C.GoBytes来获取一个字节数组,但是从那里开始,我有点迷失,因为我必须从字节数组转换为指针数组,然后再转换为字节数组,最后转换为浮点数数组。

至少我认为我需要这样做。

我看到过一些代码示例,用C数组数据替换了底层的Go切片,但我相信在这些情况下,Go的垃圾回收器不会收集它们。理想情况下,matrix [][]float32应该像普通的Go切片一样工作。

编辑:
文档是错误的,底层的C类型实际上是一个包含16个元素的浮点数数组。

所以问题变成了,我可以使用指向数组的指针的指针来使用C.GoBytes吗?如果可以,如何从[]byte获取[]float32?

英文:

I'm trying to call a function in a C++ library with a C compatible header, which wants me to pass in a 4x4 matrix for it to populate.

My Go function definition looks like this:<strike>

func GetMatrix(matrix [][]float32)

</strike>

func GetMatrix(matrix []float32)

And the c header defines it like this:

void getMatrix(const float **matrix)

<strike>I've tried using C.GoBytes to get a byte array, but then from there I'm a little lost as I have to go from a byte array to an array of pointers, which I then again convert to an array of bytes, and eventually an array of floats.

At least I think that's what I need to do.

I've seen examples of code replacing the underlying Go slice with the C array data, but I believe in those cases, the Go GC won't collect them. Ideally matrix [][]float32 would behave like a normal Go slice.</strike>

Edit:
The documentation was incorrect, and the underlying C type is actually a 16 element float array.

So the question then becomes, can I use C.GoBytes with a pointer, to a pointer of an array, and if so, how do I get a []float32 from []byte?

答案1

得分: 1

Edited 这打印出正确的东西

package main

/*
#include <stdio.h>
void getMatrix(const float **matrix){
    float *m = (float *)matrix;
    int i;
    for(i = 0; i<9; i++) {
        printf("%f\n",m[i]);
    }
}
*/
import "C"
import "unsafe"

func main() {
    a := []float32{1,2,3,4,5,6,7,8,9}
    C.getMatrix((**C.float)(unsafe.Pointer(&a[0])))
}
英文:

Edited This prints the right stuff

<!-- language: lang-go -->

package main

/*
#include &lt;stdio.h&gt;
void getMatrix(const float **matrix){
	float *m = (float *)matrix;
	int i;
	for(i = 0; i&lt;9; i++) {
		printf(&quot;%f\n&quot;,m[i]);
	}
}
*/
import &quot;C&quot;
import &quot;unsafe&quot;

func main() {
	a := []float32{1,2,3,4,5,6,7,8,9}
	C.getMatrix((**C.float)(unsafe.Pointer(&amp;a[0])))
}

答案2

得分: 1

这是一种将指向Go数组的指针传递给C函数的方法,以便C函数可以填充它:

package main
/*
#include <stdio.h>
void getMatrix(float *m) {
    int i;
    for(i = 0; i < 16; i++) {
        m[i] = (float)i;
    }
}
*/
import "C"
import "fmt"
func main() {
    var a [16]float32
    C.getMatrix((*C.float)(&a[0]))
    fmt.Println(a)
}
英文:

Here's a way to pass a pointer to a go array to a C function, so the C function can populate it:

package main
/*
#include &lt;stdio.h&gt;
void getMatrix(float *m) {
    int i;
    for(i = 0; i &lt; 16; i++) {
        m[i] = (float)i;
    }
}
*/
import &quot;C&quot;
import &quot;fmt&quot;
func main() {
    var a [16]float32
    C.getMatrix((*C.float)(&amp;a[0]))
    fmt.Println(a)
}

答案3

得分: 0

我认为你需要使用的Go类型是

*[16]*float32

无论如何,[][]float32永远不会与C的**float兼容。

英文:

I think that the Go type you'll have to use is

*[16]*float32

In any case the [][]float32 is never going to be compatible with **float of C.

答案4

得分: 0

Pointer to 4x4 array of arrays has type *[4]*[4]float32.

英文:

Pointer to 4x4 array of arrays has type *[4]*[4]float32.

答案5

得分: 0

package main

import "C"
import "unsafe"

func main() {
// 创建一个连续的16个元素的数组,但按照描述的方式组织它。
a := [4][4]float32{
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12},
{13, 14, 15, 16},
}
m := &a // 取指针。
C.getMatrix((**C.float)(unsafe.Pointer(&m))) // 取句柄并传递。
}

英文:

Extending on the answer provided by Inuart:

package main

/*
#include &lt;stdio.h&gt;
void getMatrix(const float **matrix){
    float *m = (float *)*matrix;
    int i;
    for(i = 0; i&lt;16; i++) {
       printf(&quot;%f\n&quot;,m[i]);
    }
}
*/
import &quot;C&quot;

import &quot;unsafe&quot;

func main() {
    // Create the contiguous 16 element array, but organise it how it is described.
	a := [4][4]float32{
		{1, 2, 3, 4},
		{5, 6, 7, 8},
		{9, 10, 11, 12},
		{13, 14, 15, 16},
	}
	m := &amp;a // Take the pointer.
	C.getMatrix((**C.float)(unsafe.Pointer(&amp;m))) // Take the handle and pass it.
}

This give you the handle behaviour that you seem to be asking for and has the advantage that the shape of the data in Go is as it appears to be asked for by the C API - there's no need to eschew the ease of use and safety of Go, just because you are interfacing with C.

huangapple
  • 本文由 发表于 2012年5月24日 05:33:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/10728197.html
匿名

发表评论

匿名网友

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

确定