Что вы пытаетесь сделать, это выделить некоторую память на своем языке сценариев, сохранить внутри нее объект C++ и затем получить к нему доступ позже.
Общие проблемы вы сталкиваетесь являются:
Сохранение объекта в соответствии с правилами C++.
Возвращение.
Учитывая некоторый тип T
, если этот тип копируемый или подвижен, вы всегда можете копировать/перемещать построить его в выделение, которое является достаточно большим, чтобы хранить T
и правильно выровнено.Код, который довольно прост:
void func(T t)
{
void *alloc = GetAllocation(sizeof(T), alignof(T));
new(alloc) T(t);
}
Где GetAllocation
это то, что вам нужно сделать, чтобы выделить память в системе скриптов. Синтаксис размещения new
будет строить объект типа T
, в этом случае путем копирования с t
. Вы также можете двигаться: new(alloc) T(std::move(t));
.
О, и вам также понадобится выполнить любую гимнастику, которую требует ваша система сценариев, чтобы этот объект получил свой деструктор, как только скрипт закончит с ним. Обычно это связано с регистрацией какой-либо функции со скриптовой системой для этого конкретного объекта. Но разрушение объекта опускается на шаг 2.
Но это была легкая часть. Жесткая часть получает эти данные и снова использует их. Например, если скрипт пытается вызвать эту функцию, вам придется прикрепить к ней какой-то крючок, который позволит вашему коду знать, чтобы вызвать его. И когда это произойдет, оно должно восстановить построенное значение типа T
.
Проблема для вас заключается в следующем: вы действительно не знаете, какой тип T
есть.
Если функция была передана лямбдой, вы не знаете, что это такое. . Ох, вы можете использовать decltype
для доступа к типу. Но это только потому, что для регистрации была передана значение этого типа.
На принимающей стороне, со своего языка сценариев, все, что у вас есть, это void*
. И C++ не имеет способа записать, какой тип вы использовали напрямую.
Конечно, у C++ есть способы скрыть тип, чтобы впоследствии его можно было восстановить. Обычно это называется стиранием типа: у вас есть один тип, который может содержать значение многочисленных типов, если у них есть определенный интерфейс. И это позволит вам взаимодействовать со значением, не зная его типа.
std::function
- такой тип объектов функции. Он может принимать любой тип, который является вызываемым: указатели на функции, указатели элементов, функторы и лямбды (aka: functors). Поскольку вызов - это то, что вы хотите, это должен быть приемлемый объект с стиранием.
До тех пор, пока вы знаете, какая подпись будет регистрироваться, каждая регистрационная функция будет регистрироваться. В конце концов, подпись для функций, которые она несет, является частью типа для std::function
. Таким образом, вам придется стандартизировать такие функторы для конкретной сигнатуры, которая известна в то время, когда функтор зарегистрирован в системе сценариев.
У вас могут быть разные функции, которые регистрируют разные подписи. Действительно, вы можете создавать такие шаблоны функций. Но вам все равно нужно знать, когда определенная функция регистрируется, какова ее подпись.
Это также важно для уничтожения объекта во время GC, так как вам нужно его вернуть.
Я не понял все это, но по существу вы хотите сериализовать захваченные значения? Или целая функция? Что насчет ссылок и т. Д.? – deviantfan
Нужно ли десериализовать сериализованную версию лямбда после выхода текущего экземпляра текущей программы? –
Могли бы вы рассказать о том, как на самом деле вы будете использовать это? Я не понимаю, почему вам нужно сериализовать lambdas, когда все, что вам нужно, это создать привязку к языку ...? –