У меня есть библиотека Go, gofileseq, для которой я хотел бы попробовать и сделать привязку C/C++.Можно ли экспортировать/обернуть комплекс Go struct в C?
Это довольно просто, чтобы иметь возможность экспортировать функции, которые используют простые типы (ints, string, ...). Достаточно легко экспортировать данные из пользовательских типов Go в C, определив структуру C и переведя в нее тип Go, который будет использоваться в экспортируемых функциях, поскольку вы выделяете C-память для этого. Но с go 1.5 cgo rules мне трудно понять, как экспортировать функциональность из более сложной структуры, которая хранит состояние.
Пример структуры из gofileseq, что я хотел бы экспортировать как-то на C++ Переплета:
// package fileseq
//
type FrameSet struct {
frange string
rangePtr *ranges.InclusiveRanges
}
func NewFrameSet(frange string) (*FrameSet, error) {
// bunch of processing to set up internal state
}
func (s *FrameSet) Len() int {
return s.rangePtr.Len()
}
// package ranges
//
type InclusiveRanges struct {
blocks []*InclusiveRange
}
type InclusiveRange struct {
start int
end int
step int
cachedEnd int
isEndCached bool
cachedLen int
isLenCached bool
}
Как вы можете видеть, FrameSet
типа, который я хочу, чтобы разоблачить содержит кусочек указателей на основополагающий тип, каждый из которых хранит состояние.
В идеале, я хотел бы иметь возможность хранить void*
в классе C++ и сделать его простым прокси для возврата в экспортированные функции Go с помощью void*
. Но правила cgo запрещают C хранить указатель Go дольше, чем вызов функции. И я не понимаю, как я мог бы использовать подход определения классов C++, который можно было бы назначить и использовать для работы с моей библиотекой Go.
Можно ли обертывать сложные типы для воздействия на C/C++? Есть ли шаблон, который позволил бы клиенту C++ создать Go FrameSet
?
Редактировать
Одна идея, которую я могу думать о том, чтобы позволить C++ создавать объекты в Go, которые откладываются на стороне Go в статическом map[int]*FrameSet
, а затем вернуть Int идентификатор в C++. Затем все операции C++ делают запросы в Go с идентификатором. Это похоже на правильное решение?
Update
На данный момент я исхожу с тестированием решение, которое использует глобальные карты и уникальные идентификаторы для хранения объектов. C++ запрашивает создание нового объекта и возвращает только непрозрачный идентификатор. Затем они могут вызывать все методы, экспортируемые как функции, используя этот идентификатор, включая запрос на его уничтожение, когда это делается.
Если есть лучший подход, чем это, я хотел бы получить ответ. Как только я получу полноценный прототип, я добавлю свой собственный ответ.
Update # 2
Я написал в блоге о том, что окончательное решение я кончался с помощью: http://justinfx.com/2016/05/14/cpp-bindings-for-go/