2014-02-09 2 views
1

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

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

type Device struct { 
    d *C.nfc_device 
} 

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

  • Сделать d общественного член Device

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

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

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

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

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

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

ответ

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.

+0

спасибо. Я решил реализовать его таким образом. – fuz