Не зная реализации пользовательских данных, могу ли я использовать его поля изнутри С++?

Я могу получить пользовательские данные из своего кода C++. Я хочу знать, могу ли я привести его к чему-то, чтобы я мог разыменовывать его поля и вызывать его методы, не проходя через Lua.

Другими словами:

Как только я получу пользовательские данные и положу их в стек Lua, как я могу получить их и использовать как объект определенного класса? Я знаю все интересующие меня поля и методы (их имена в Lua), но не обязательно все поля и методы, которые предоставляет базовая реализация пользовательских данных.

Есть ли способ как-то создать интерфейс, который бы знал смещения каждого члена?

Я считаю, что вопрос в том, как мне узнать смещение каждого члена в представлении Lua пользовательских данных, чтобы я мог создать структуру для приведения void *, возвращаемого lua_touserdata?


person FinnTheHuman    schedule 29.04.2017    source источник


Ответы (1)


Пользовательские данные — это просто двоичный объект. Массив байтов. Как эти байты будут интерпретироваться - полностью зависит от интерфейса, предоставленного с этими пользовательскими данными, будь то метаданные с методами или какие-то другие соглашения.

Если эти пользовательские данные созданы вашим кодом, то вы либо знаете, какой тип собственного объекта существует (зная, что некоторые функции генерируют или принимают только определенный тип), либо вы можете поместить идентификатор типа в качестве первых байтов большого двоичного объекта пользовательских данных, чтобы вы могли проверить это id и переключить/привести указатель пользовательских данных к определенному классу.

Если эти пользовательские данные созданы чьим-то кодом - вы можете полагаться только на методы, предоставленные в его метатаблице (вы можете получить к ней доступ из собственного кода), или просто рассматривать их как массив байтов, возможно, не зная фактический тип данных, хранящихся там. Или сделайте несколько хакерских догадок, чтобы в некоторых случаях это работало, и сильно зависало, если ваша догадка была неверной.

person Vlad    schedule 29.04.2017
comment
Нет никакого способа запросить у Lua смещение данного члена? - person FinnTheHuman; 29.04.2017
comment
@FinnTheHuman: члены пользовательских данных не обязательно соответствуют какому-либо «настоящему» (под) объекту C; они просто синтаксический сахар для вызовов метаметодов __index или __newindex. Поскольку эти метаметоды могут делать что угодно и не ограничиваются простым возвратом фиксированной ссылки на часть большого двоичного объекта, Lua не может дать смещение для данного члена. Если вы просто хотите сделать эквивалент вызова этих метаметодов, но из C, а не из Lua, просто используйте lua_getfield или lua_setfield (которые вызовут любые метаметоды, если они присутствуют). - person Mankarse; 29.04.2017
comment
@Mankarse Спасибо. Значит, единственный способ пропустить Lua — заставить автора типа создать для него реальный интерфейс? - person FinnTheHuman; 29.04.2017
comment
@FinnTheHuman: Да. Вам нужно, чтобы автор предоставил функции, которые работают с непрозрачным указателем на тип пользовательских данных, или вам нужно, чтобы автор предоставил объявления структур, которые представляют гарантированный интерфейс; которому вы могли бы передать пользовательские данные. - person Mankarse; 29.04.2017