Следуйте десятому закону Гринспуна, и все готово: просто внедрите специальную, неофициально заданную, подверженную ошибкам, медленную реализацию половины Common Lisp. Выберите половину, которая поддерживает реализацию отражения. :)
Или вот идея:
Включите файлы карт (и, возможно, генерацию сборок) в вашей сборке. Реализуйте приложение, которое генерирует код для создания динамической библиотеки. Вы должны иметь возможность получать всю статическую информацию (имена методов, параметры, типы и т. Д.) О классах либо из источника, либо из одного из артефактов сборки. Используя карту или сборку, вы сможете найти адреса функций, смещения указателей виртуальных функций, адреса глобальных переменных, смещения переменных, информацию о стеке и регистре распределенных переменных и т. Д. И т. Д. Из этой информации создайте библиотеку, содержащую вызовы для получения всей этой информации путем передачи имен типов, указателей, имен функций и т. Д.
Теперь в C ++ напишите библиотеку, содержащую функции и макросы, которые позволят вам помещать уникальные идентификаторы, которые будут скомпилированы в код для определения запуска функций, всех вызовов отражения, смещения EIP при вызовах отражения и т. Д. Используйте встроенные макросы сборки в соответствующих местах, где по мере необходимости оставляются комнаты с NOP, чтобы поместить несколько инструкций, если это необходимо, обычно сразу после удостоверения личности. Кроме того, предоставьте функции библиотеки мостов, которые позволят функции отражения либо обрабатывать то, что она может встроить (скажем, получить адрес функции), чем выполнять вызовы динамической библиотеки, встроенной в шаг после сборки.
Наконец, напишите компоновщик отражения пост-пост сборки. Я предлагаю "kniltsoPostlink", но это зависит от вас. На этом шаге ищите ваши уникальные идентификаторы (я упомянул, чтобы упростить, вы, вероятно, должны сделать идентификаторы GUID, чтобы вы могли искать их в двоичном файле?) И, где идентификатор помечает вызов отражения функции или определение класса и т. д., поместите туда достаточно данных (в формате, который вы можете легко определить точно в срок при написании библиотеки отражателей), а затем в идентификаторе перед вызовом библиотеки отражателей перепишите вызов так, чтобы он извлекает необходимые параметры из этих битов данных или просто помещает биты данных туда, где это применимо, я не могу знать заранее, но по мере того, как вы пишете это, эти маленькие детали просто всплывают у вас.
В любом случае, я знаю, что я не дал много кода, и я действительно собираюсь начать проект по этому вопросу в какой-то момент, когда у меня будет достаточно свободного времени. Я имею в виду, что каждая маленькая часть должна быть очень простой, так что если вы делаете это постепенно, каждая маленькая часть должна становиться понятной, если вы следуете рекомендациям, изложенным здесь. Возможно, что некоторые из них будут даже проще, чем я описал здесь, потому что это был худший сценарий. Вы можете даже уйти без необходимости вообще переписывать код для вызовов отражателя; простое размещение данных в соответствующих местах может позволить библиотеке извлекать эти биты по мере необходимости, без дополнительной информации.
Я очень рад, что вы спросили; Я сейчас очень занят, но если у вас будет свободная ночь, я думаю, что это будет хорошим началом для первой версии, и я буду рад присоединиться, как только смогу.
;)