编组无法从 Go 访问的 C 对象

2024-04-19

有一些 C 对象,例如联合体、包含位域的结构体以及其对齐方式与 Go 的 ABI 不同的结构体,无法从 Go 访问。其中一些结构无法更改为可从 Go 代码访问,因为它们是现有库的 API 的一部分。

因此,要将这些对象编组到 Go 结构中,我们无法真正使用 Go 代码。相反,我们必须用 C 编写编组代码。这工作得很好,但我还没有找到一种可行的方法来定义对 Go 代码中定义的类型进行操作的 C 函数。现在,我正在定义要在 C 端编组的数据类型,并在我的 Go 代码中使用这些数据类型。

如果我想在 Go 代码中将编组类型公开为 API,这真的很糟糕,因为我无法将 C 类型公开为包接口的一部分。我当前的方法是将已经编组的对象重新编组为 Go 代码中定义的类型。

有没有更优雅的方式来做我想做的事情,即将无法从 Go 代码访问的 C 结构编组为 Go 代码中定义的数据类型?

根据评论部分的要求,这里是无法从 Go 访问的 C 对象的集合。

#include <complex.h>
#include <stdbool.h>

union foo {
    int i;
    float f;
};

struct bar {
    bool x:1;
    unsigned int y:3;
    unsigned int z:4;
};

struct baz {
    float f;
    complex float c;
};

#pragma pack 1
struct quux {
    char c;
    short s;
    int i;
};

标准套餐encoding/binary可用于操作原始 C 结构。 您可以扩展读取和写入功能以支持自定义类型:

func Read(r io.Reader, order binary.ByteOrder, data interface{}) error {
    switch data := data.(type) {
    case *foo:
        return readFoo(r, order, data)
    // (...)
    default:
        return binary.Read(r, order, data)
    }
}

func Write(w io.Writer, order binary.ByteOrder, data interface{}) error {
    switch data := data.(type) {
    case foo:
        return writeFoo(r, order, data)
    // (...)
    default:
        return binary.Write(r, order, data)
    }
}

使用包含所有联合字段的结构,并使用应用程序上下文来决定将哪个值编码到 C 联合中。

type foo struct {
    is_i bool
    i    int32
    f    float32
}

// Read a foo from r into data
func readFoo(r io.Reader, order binary.ByteOrder, data *foo) error {
    b := make([]byte, 4)
    if _, err := io.ReadFull(r, b); err != nil {
        return err
    }

    *data = foo{
        i: int32(order.PutUint32(b)),
        f: float32(order.PutUint32(b)),
    }

    return nil
}

// Write a foo from data into w
func writeFoo(w io.Writer, order binary.ByteOrder, data foo) error {
    b := make([]byte, 4)

    if data.is_i {
        order.PutUint32(b, uint32(data.i))
    } else {
        order.PutUint32(b, uint32(data.f))
    }

    _, err := w.Write(b)
    return err
}

(或者,使用 getter 和 setter:http://pastebin.com/H1QW5AFb http://pastebin.com/H1QW5AFb)

使用按位运算来封送位域

type bar struct {
    x bool
    y uint
    z uint
}

// Read a bar from r into data
func readBar(r io.Reader, order binary.ByteOrder, data *foo) error {
    b := make([]byte, 1)
    if _, err := io.ReadFull(r, b); err != nil {
        return err
    }

    // Read from bitfield
    *data = bar{
        x: bool(b[0] >> 7),          // bool x:1;
        y: uint((b[0] & 0x70) >> 3), // unsigned int y:3;
        z: uint(b[0] & 0x0f),        // unsigned int z:4;
    }

    return nil
}

// Write a bar from data into w
func writeBar(w io.Writer, order binary.ByteOrder, data bar) error {
b := make([]byte, 1)

    var x uint8
    if data.x {
        x = 1
    }
    // Create bitfield
    b[0] = (x & 0x01 << 7) & // bool x:1;
        (uint8(data.y) & 0x03 << 4) & // unsigned int y:3;
        (uint8(data.z) & 0x04) // unsigned int z:4;
    _, err := w.Write(b)
    return err
}

baz 的序列化形式取决于编译器对complex 的内部定义。 使用时encoding.binary,字段具有 1 字节对齐方式,因此 quux 可以直接封送。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

编组无法从 Go 访问的 C 对象 的相关文章

随机推荐

  • 如何使用 jQuery 获取 的内容?

    如何获取跨度的 这是我的名字 内容 div span This is my name span div 我认为这应该是一个简单的例子 item1 span text or item1 span html
  • 等待 GUI 中显示多个任务

    假设我有两个资源A and B 我想通过 MVVM 向我的用户展示这两个内容 this 视图模型 this A GetA this B GetB 当我开始使用 TPL 时 this A await GetAAsync this B awai
  • Firefox 和 Chrome 中的输入高度差异

    为什么Chrome的输入高度比Firefox大 请参阅此处的示例http jsfiddle net jitendravyas 89Msh 1 http jsfiddle net jitendravyas 89Msh 1 select inp
  • 您可以预加载相关数据,以便将您的关系缓存在 ember-data 中吗?

    我有一个简单的 hasMany belongsTo 关系 如下所示 App Foo DS Model extend bar belongsTo bar async true App Bar DS Model extend foos hasM
  • JavaScript/jQuery 中括号中的代码块意味着什么? [复制]

    这个问题在这里已经有答案了 可能的重复 function jQuery 是什么意思 意思是 https stackoverflow com questions 2937227 jquery what does function jquery
  • CodeIgniter 4 模型->find()

    如果这个问题之前已经问过 我很抱歉 所以我想做的是从我的模型中得到这样的结果 data userModel gt where username myname gt find 我的期望 data id gt 1 username gt myn
  • 仅当 S 和 T 不同时,Func 的 T 才从 lambda 表达式的输出推断出来?

    When S and T是不同的 这有效 public static void Fun
  • SugarORM 从多个表查询?

    我正在为我的 Android 应用程序使用 SugarORM 在我的项目中 我有几个表 我想知道是否有一种方法可以将它们连接到另一个具有多个表中的列的类对象中 如果是 那么示例将非常有帮助 SugarORM 提供了一个用于简单查询的查询生成
  • 在 beforeRemote 远程挂钩内添加过滤器

    我有一个问题 在 Loopback 的文档中找不到答案 说我有一个模型Company和一个模型Employee 之间存在 1Xn 关系Company和它的Employees When api Employees被调用时 服务器返回所有员工
  • Windows 服务应该在哪里写入应用程序数据?

    我们有一个 Windows 服务作为我们软件的一部分 即使没有用户登录系统 它也可以在后台将数据传输到远程数据库 目前 这些数据缓存在 Program Files 目录中 我认为这不是一个好主意 因为它要求我们减少 Program File
  • 编程语言中的协变和逆变有什么区别? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 谁能解释一下协变和逆变的概念 编程语言理论 协方差非常简单 最好从某个集合类的角度来思考List 我们可以参数化 the List具有
  • Xamarin 表单按钮没有边框问题

    我尝试在视图中呈现可点击项目的列表 我想添加一个带有图像和白色边框的按钮 第一个 我发现 StackLayout ViewCell 中的按钮无法渲染边框
  • 如何同时使用 2 个范围滑块?

    我想使用 2 个范围滑块同时根据年龄和身高过滤表中的数据 我已经使用以下方法实现了 2 个范围滑块 年龄和身高 d3 slider js https github com MasterMaps d3 slider and a dc data
  • 身份验证超时无法正常工作

    我有一个 ASP NET 4 网站 我在 web Config 中将身份验证超时设置为 100 分钟 但是当用户使用网站时 网站甚至在 3 分钟后突然提示登录 下面的代码是我的 web Config 文件
  • 寻找成熟的 M-Tree 实现 [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我正在寻找一个成熟的 java M Tree 实现 甚至任何 M Tree 实现 除了我找到的唯一实现 http en wikipedia
  • Mockito.anyString() 在 Kotlin 中因 NPE 崩溃

    我正在使用浓缩咖啡 我想为内容解析器创建一个模拟响应 当我使用时 when context activity contentResolver query ArgumentMatchers isA Uri class java Argumen
  • famo.us:如何处理 textbox.onchange 事件

    我在famo us 大学上没有看到任何带有文本输入的教程 如何将文本框表面添加到我的应用程序并处理onchange events 有点难以理解你想要做什么 但是让我们从你的第一个问题开始 目前没有 onchange 处理程序选项 因此如果您
  • 为什么 JavaScript 中的数字是不可变的?

    我在这里阅读了问题和答案 javascript 数字 不可变 https stackoverflow com questions 8248568 javascript numbers immutable 但我还不清楚为什么数字 原始类型 是
  • 如何处理重复事件中的 DST 和 TZ?

    dateutil rrule 是否支持夏令时和夏令时 需要类似于 iCalendar RRULE 的东西 如果不是 如何解决这个问题 安排重复事件和 DST 偏移量更改 Imports gt gt gt from django utils
  • 编组无法从 Go 访问的 C 对象

    有一些 C 对象 例如联合体 包含位域的结构体以及其对齐方式与 Go 的 ABI 不同的结构体 无法从 Go 访问 其中一些结构无法更改为可从 Go 代码访问 因为它们是现有库的 API 的一部分 因此 要将这些对象编组到 Go 结构中 我