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

Которые ты напишешь..

expelled ★★
()
Последнее исправление: expelled (всего исправлений: 1)
Ответ на: комментарий от 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
()
Вы не можете добавлять комментарии в эту тему: топик перемещен в архив.