如何在Go中访问C位域 [英] How to access C bitfield in Go

查看:94
本文介绍了如何在Go中访问C位域的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个像这样的结构:

I have a struct like so:

typedef struct st_MASK_SETTINGS
{
  uint32_t foo  : 1;
  uint32_t bar  : 7;
} MASK_SETTINGS

现在通过cgo我想访问 foo -但找不到任何文档.

Now through cgo I would like to access foo - but cannot find any documentation how to do so.

天真的 v:= ms.foo 抱怨没有字段或方法.

推荐答案

好吧,你不会喜欢这个答案,但是

Well you won't like this answer, but

    没有实现此目的的便携式方法,因为位域打包是实现定义的".在C和C ++中,以及
  1. Go中对位域的支持似乎很糟糕(也许是由于#1).
  1. there is no portable way to do this because bitfield packing is "implementation-defined" in both C and C++, and
  2. bitfield support in Go seems fairly crappy (perhaps due to #1).

首先,在每个现有的C和C ++标准中,位域的布局都是实现定义的.这意味着没有一个标准指定应如何打包位字段定义中的位(即它们应该去哪里)-这完全取决于编译器.在给出一些编译器样本的情况下,您可能会发现它们的布局方式在实践中,但是您将深入研究未定义的行为领域.

First of all, the layout of bitfields is implementation-defined in every existing C and C++ standard. This means that none of the standards specify how bits in a bitfield definition should be packed (i.e., where they should go) -- it's totally up to the compiler. You may find how they are laid out to be a certain way in practice given a few compiler samples, but you will be deep into undefined behavior territory.

我们正在gcc中的错误#83784 (并且我们"是指安德鲁·平斯基),我希望在gcc 10或11中我们将有一个最佳解决方案.要明确的是,现在有一个解决方案-它使用联合并定义打包和解压缩函数来读取每个位域,然后将数据手动放入内存中.问题是,当您正确地猜测gcc使用的位布局时,该功能应变为无操作且编译离开".目前这还没有发生.

We are working on this issue in gcc under bug #83784 (and by "we" I mean Andrew Pinski), and I'm hoping that in gcc 10 or 11 we'll have an optimal solution. To be clear, there is a solution now -- it is use a union and define pack and unpack functions to read each bitfield and manually put the data where it belongs in memory. The issue is that when you have properly guessed the bit layout gcc uses then the function should become no-ops and "compile-away". This is currently not happening.

示例:

union a {
    struct {
        int field1:12;
        int field2:20;
    };
    int packed;
};

static union a a_pack(union a a)
{
    union a ret = {0};

    ret.packed = (a.field1 & ((1 << 12) - 1) << 20;
    ret.packed |= a.field2 & ((1 << 20) - 1)

    return ret;
}

static union a a_unpack(union a a)
{
    union a ret = {0};

    ret.field1 = a.packed >> 20;
    ret.field2 = a.packed & ((1 << 20) - 1);

    return ret;
}

执行此操作后,您可以打包"您的位域,请从Go中读取打包的内容,然后对它进行小提琴或使用其中一种位域实现.

Once you do this, you can "pack" your bitfield, read a.packed from Go and then either bit fiddle it or use one of the bitfield implementations.

我告诉过你,你不想要答案.:)

I told you you wouldn't like the answer. :)

这篇关于如何在Go中访问C位域的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆