如何提供对cgo包装的库的访问?

时间:2014-02-09 00:21:36

标签: c go wrapper accessor cgo

我正在尝试为C库编写绑定,特别是libnfc。我目前的代码可在Github上找到。

libnfc中的一个核心结构是设备。它由Go类型Device表示。

type Device struct {
    d *C.nfc_device
} 

Device上运行的libnfc中的所有函数都是它的方法。现在,还有其他C库(例如libfreefare),其API在nfc_device es上运行。为了模块化,我想将每个库的代码放入我自己的模块中。这导致了一个问题,即我无法从其他模块中访问私有结构成员。我想到了以下解决方案:

  • d成为Device

    的公共成员

    这样可以轻松地从其他模块中访问基础nfc_device,但这也使得回避类型安全变得容易。另外,我不知道cgo是否识别指向外部类型的指针,如果它们来自不同的模块。最后,如果我更改了设备类型的结构,我将失去灵活性。

  • 添加访问者func (Device) GetCPtr() unsafe.Pointer

    这解决了上述问题,但介绍了您突然有权访问模块中可能无法导入unsafe.Pointer的新问题。

  • 添加访问者unsafe

    这解决了上述问题,因为您必须手动转换结果才能获得正确的指针。

我有什么方法可以错过吗?是否有更好,更惯用的方式来提供对基础func (Device) GetCPtr() uintptr的访问?

1 个答案:

答案 0 :(得分:1)

我一般赞成你的第三个提案,因为这是reflect package handles this issue的方式。

您还可以做的是只在libnfc包装器中公开一个接口,例如:

type NFCDevice interface {
    Read() ([]byte, error)
    Write() ([]byte, error)
    // ...
}

现在你有一个安全的公共API。

此外,您的device类型实现了一个功能

func (d *device) NfcDevice() *C.nfc_device {
    return d.nfc_device
}

你可以在你的其他包装器中使用断言你的NFCDevice来实现 接口

interface {
    NfcDevice() *C.nfc_device
}

您可以在其他包装器中动态创建。这样程序员就必须刻意去做 做一些事情来访问device

的内部工作原理