Свяжите уникальный идентификатор с определениями функций ржавчины

У меня есть структура, которую я хотел бы сериализовать на диск как часть формата файла сохранения JSON. (Упрощенная) структура структуры выглядит следующим образом:

pub struct Effect {
  pub source: Source,
  pub duration: Duration,
  pub implementation: fn(&mut GameState, Source) -> Result<()>
}

Я хотел бы сериализовать эту структуру через serde. Сериализация указателей функций, конечно, невозможна, поэтому я хочу аннотировать каждую функцию, которую я использую, как implementation с уникальным идентификатором, записать этот идентификатор как часть сохраненного JSON, а затем использовать идентификатор для поиска функции. указатель, который будет использоваться при десериализации структуры, возможно, путем создания большой карты functionId->functionPointer в качестве первого шага. Есть ли хороший способ пометить определения функций такими метаданными?

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

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

drewtato 16.07.2024 23:53

Построить отображение fnId->fnPtr несложно, по крайней мере вручную, но вообще невозможно построить обратное отображение, так как одна и та же функция может иметь несколько адресов. Таким образом, единственный жизнеспособный способ, как сказал @drewtato, - каким-то образом закодировать идентификатор в самом коде функции. Это может быть тип возвращаемого значения или более экзотические способы, такие как интерпретация машинного кода функции с некоторым известным префиксом.

Chayim Friedman 17.07.2024 00:10
Почему Python в конце концов умрет
Почему Python в конце концов умрет
Последние 20 лет были действительно хорошими для Python. Он прошел путь от "просто языка сценариев" до основного языка, используемого для написания...
0
2
56
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Указатели функций указывают непосредственно на машинный код. К ним невозможно прикрепить дополнительные метаданные. Вы также не можете сравнивать указатели функций: вы можете получить как ложноотрицательные результаты (функции, которые были скомпилированы дважды), так и ложноположительные результаты (функции, машинный код которых был дедуплицирован с другой функцией, которая имеет идентичный код).

Единственный способ получить достоверную информацию об указателе функции — это вызвать ее и посмотреть, что она делает. Но в этот момент вы могли бы вместо этого использовать объект типажа, а не увлекаться сигнатурой функции. Объект типажа может иметь метод для выполнения операции и метод для запроса его идентификатора в таблице сериализации.

В качестве альтернативы, если вам все равно нужно построить таблицу и все возможные параметры известны во время компиляции, перечисление также будет уместным.

cdhowie 17.07.2024 10:02

честно говоря, единственным разумным решением, вероятно, является какая-то схема «толстого указателя», где каждый указатель функции также несет идентификатор для сериализации и реализует признак Fn, но автоматическое присвоение такого идентификатора было бы очень сложно (возможно, вам придется каким-то образом создать собственный const POINTER для каждой функции со своим указателем и использовать его везде вместо исходного указателя?)

Derek Thurn 17.07.2024 16:08

Другие вопросы по теме