我正在尝试为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
的访问?
答案 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
。