Как мне предоставить доступ к библиотеке, которую я оборачиваю с помощью cgo?

Я пытаюсь написать привязки для библиотеки C, в частности для libnfc. Мой текущий код доступен на Github.

Одной из центральных структур libnfc является устройство. Он представлен типом Go Device.

type Device struct {
    d *C.nfc_device
} 

Все функции внутри libnfc, работающие с Device, являются его методами. Теперь есть и другие библиотеки C (например, libfreefare), чьи API работают с nfc_devicees. Ради модульности я хочу поместить код каждой библиотеки, которую я оборачиваю, в отдельный модуль. Это приводит к проблеме, что я не могу получить доступ к членам частной структуры из других модулей. Я думал о следующих решениях:

  • Сделать d общедоступным участником Device

    Это облегчило бы доступ к базовому nfc_device из других модулей, но также позволяет легко обойти безопасность типов. Кроме того, я не знаю, распознает ли cgo указатели на внешние типы, если они исходят из разных модулей. Наконец, я теряю гибкость, если изменяю структуру типа устройства.

  • Добавьте аксессуар func (Device) GetCPtr() unsafe.Pointer

    Это решает описанные выше проблемы, но вводит новую проблему, заключающуюся в том, что вы внезапно получаете доступ к unsafe.Pointer в модуле, который может даже не импортировать unsafe.

  • Добавьте аксессуар func (Device) GetCPtr() uintptr

    Это решает вышеупомянутую проблему, так как вам нужно вручную привести результат, чтобы получить правильный указатель.

Есть ли способы, которые я пропустил? Есть ли лучший, более идиоматический способ предоставить доступ к базовому nfc_device?


person fuz    schedule 09.02.2014    source источник


Ответы (1)


В целом я поддерживаю третье ваше предложение, поскольку именно так пакет reflect обрабатывает это. проблема.

Что вы также можете сделать, так это открыть только интерфейс в вашей оболочке 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.

person nemo    schedule 09.02.2014