在Go语言中访问原始C结构体的字段。

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

Accessing field on original C struct in Go

问题

我正在尝试使用Go语言中的OpenCV。OpenCV定义了一个名为CvMat的结构体,其中包含一个data字段:

typedef struct CvMat
{
    ...
    union
    {
        uchar* ptr;
        short* s;
    } data;
}

我正在使用这里找到的go-opencv绑定。它为CvMat定义了一个类型别名:

type Mat C.CvMat

现在我有一个Mat对象,我想访问它的data字段。我该如何做?如果我尝试访问_data,它不起作用。我使用reflect包打印了Mat对象的字段,得到了以下结果:

...
{data github.com/lazywei/go-opencv/opencv [8]uint8  24 [5] false}
...

所以它确实有一个data字段,但它甚至不是相同的类型。它是一个包含8个uint8的数组!我正在寻找一个比8个字符长得多的uchar*指针。我该如何获取这个uchar指针呢?

英文:

I'm trying to use OpenCV from Go. OpenCV defines a struct CvMat that has a data field:

typedef struct CvMat
{
    ...
    union
    {
        uchar* ptr;
        short* s;
    } data;
}

I'm using the go bindings for opencv found here. This has a type alias for CvMat:

type Mat C.CvMat

Now I have a Mat object and I want to access the data field on it. How can I do this? If I try to access _data, it doesn't work. I printed out the fields on the Mat object with the reflect package and got this:

...
{data github.com/lazywei/go-opencv/opencv [8]uint8  24 [5] false}
...

So there is a data field on it, but it's not even the same type. It's an array of 8 uint8s! I'm looking for a uchar* that is much longer than 8 characters. How do I get to this uchar?

答案1

得分: 3

简短回答是,如果不修改go-opencv,你无法做到这一点。这里有几个障碍:

  1. 当你导入一个包时,你只能使用已导出的标识符。在这种情况下,data不是以大写字母开头,所以它没有被导出。

  2. 即使它是一个已导出的标识符,你也会遇到问题,因为Go语言不支持联合类型。所以,字段被表示为与底层C联合类型大小相匹配的字节数组(在这种情况下是8个字节,与64位指针的大小相匹配)。

  3. 最后,强烈建议不要从包中公开cgo类型。所以,即使在像这样的情况下可能直接访问底层C结构的情况下,我也建议不要这样做。

理想情况下,go-opencv应该提供一个访问你所需信息的接口(可能可以检查联合类型的哪个分支正在使用,而不是返回错误数据)。我建议你要么在该包上提交一个错误报告(可能附带一个补丁),要么如果你需要立即使用该功能,就创建一个带有所需修改的私有副本。

英文:

The short answer is that you can't do this without modifying go-opencv. There are a few impediments here:

  1. When you import a package, you can only use identifiers that have been exported. In this case, data does not start with an upper case letter, so is not exported.

  2. Even if it was an exported identifier, you would have trouble because Go does not support unions. So instead the field has been represented by a byte array that matches the size of the underlying C union (8 bytes in this case, which matches the size of a 64-bit pointer).

  3. Lastly, it is strongly recommended not to expose cgo types from packages. So even in cases like this where it may be possible to directly access the underlying C structure, I would recommend against it.

Ideally go-opencv would provide an accessor for the information you are after (presumably one that could check which branch of the union is in use, rather than silently returning bad data. I would suggest you either file a bug report on the package (possibly with a patch), or create a private copy with the required modifications if you need the feature right away.

huangapple
  • 本文由 发表于 2014年9月15日 12:44:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/25840952.html
匿名

发表评论

匿名网友

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

确定