LINUX.ORG.RU

Как в C++, вызванном из Go, рефлексию по Go-структуре запилить?

 ,


0

3

Но сначала вопрос не по теме (рефлексия), а ещё суровее - о создании Go-типов из C++.

Есть некий C++ код, который пока не написан, вызываемый из Go. Ну например с помощью cgo https://golang.org/cmd/cgo/

Хочется в C++ сконструировать и вернуть в вызывающий Go-код сложную Go-структуру, типа произвольного (один из заранее известных) интерфейса, возвращающего другие интерфейсы. Некий бинарный JSON в виде вложенных интерфейсов.

var r := my_cpp_func()

// вот мы вызвали наш C++ код и нам вернулся интерфейс r.
// r может реализовывать один из заранее известных интерфейсов:
// MyArray, MyRectangle.
// C++ как-то должен про них знать и как-то говорить GC, что создал их.
// Далее мы выясняем, что это за интерфейс и дёргаем соответствующие методы.

if v, ok := r.(MyArray); ok {
    // --- ARRAY ---
    var size := v.size()
    ...
}

if v, ok := r.(MyRectangle); ok {
    // --- RECTANGLE ---
    var area := v.area();
    ...
}

Я так понимаю, хрен это получится сделать из-за уборщика мусора, который будет не в курсе, что мы там в C++ коде насоздавали. Да и вообще какой-то не трушный вей.

Ну ладно, хрен с ним.

Тогда вопрос по сабжу: передать в C++ некую go-структуру struct заранее неизвестного типа и в C++ коде по ней рефлективно пошариться. Узнать типы всех полей, увидеть вложенные структуры и т.п. Что-то им присвоить или куда-нибудь сериализовать существующую структуру. Это как-то делается?



Последнее исправление: hlamotron (всего исправлений: 4)

нет, уходи

anonymous
()

Можешь в го-структуре в начале попробовать описание структуры сохранить.

Y ★★
()

Нафиг это надо, возвращай строку json и парси в go. Либо вообще всё пиши на go и не страдай.

menangen ★★★★★
()
Ответ на: комментарий от Y

Сохранить описание структуры - не круто. Особенно не круто учитывая то, что в самом Go можно написать «обходчик» структуры родными средствами — т.е. эти средства есть, хочется за них подёргать из плюсов.

hlamotron
() автор топика

Создавать новые типы на этапе выполнения нельзя никак.

Интерфейсы тоже не делают никакой магии, кроме хранения идентификатора типа рядом с указателем. Известного при компиляции типа.

NoMasters
()
Ответ на: комментарий от hlamotron

т.е. эти средства есть, хочется за них подёргать из плюсов.

вот это и есть «не круто». зачем тебе вообще С++ в go?

dib2 ★★★★★
()
Ответ на: комментарий от dib2

С каких пор все сишные и крестовые либы переписаны на го, я что-то пропустил?

Zaskard
()
Ответ на: комментарий от NoMasters

А можно ли из C++ дёргать «методы» Go-интерфейсов, переданных в C++?

Могу я написать C++ код, который ожидает, что у переданного в него интерфейса есть метод «callme()», может проверить что этот метод есть и дёргнуть его?

Могу я в C++ рефлективно походить по Go-структуре, переданной в C++? Мне нужно в C++ коде пробежать по полям заранее неизвестной Go-структуры, переданной в однократно скомпилированную C++ библиотеку. Т.е. люди в Go придумывают новые типы и, не пересобирая C++ библиотеку .so, передают свои новые Go-структуры в C++, а C++ код понимает из чего состоит структура (типы данных) и может что-то присвоить полям.

hlamotron
() автор топика
Ответ на: комментарий от hlamotron

Для начала cgo — это чисто для С(без плюсов). Туда никаких объектов не завезли и методов, соответственно, тоже.

Вообще юзкейс не очень понятный, что в итоге хочется сделать?

По факту единственное, что можно напрямую экспортировать из go и потом адекватно использовать из сей — это функции. Можно извратиться и попробовать написать обёртку над пакетом reflect для экспорта, но зачем?

NoMasters
()
Ответ на: комментарий от NoMasters

C++ - объекты со всем полиморфизмом прекрасно живут в Си. Просто не нужно их пытаться выставить наружу. И я не понял, при чём тут объекты С++.

В итоге хочется сделать:

Есть структура Go. Хочется отдать её в C++ и там перебрать её поля, заранее не зная какие бывают Go-структуры в Go-коде.

hlamotron
() автор топика

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

Узнать типы всех полей, увидеть вложенные структуры и т.п.

Deleted
()
Ответ на: комментарий от hlamotron

https://golang.org/pkg/reflect/

Тебе придется написать над ними обертки, конвертящие interface{} в unsafe.Pointer, например.

По поводу рантайм-генерации типов — в 1.7 в reflect добавят StructOf, может, то, что тебе надо.

Но вообще это шиза какая-то.

Deleted
()
Ответ на: комментарий от menangen

всё пиши на go и не страдай

несбыточные мечты

vertexua ★★★★★
()
Ответ на: комментарий от Deleted

А потом что делать с unsafe.Pointer? Понимать как interface{} лежит в памяти, где у него там таблица функций и т.п.?

hlamotron
() автор топика
Ответ на: комментарий от Deleted

Ну вот я и говорю - т.е. приведя interface{} к void* мне надо понимать что по этому void* лежит 2 указателя, вручную их разыменовывать, получив таблицу функций и объект, ковыряться вручную в этой таблице функций?... Да ну накуй.

hlamotron
() автор топика
Ответ на: комментарий от hlamotron

Ничего ты не будешь разыменовывать, ты передашь его в свои функции-обертки на Go.

Deleted
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.