2010-02-12 3 views
7

Я думаю о добавлении каких-то возможностей отражения в некоторые классы C++ (так что мне не пришлось бы использовать RTTI): получение имен методов, объявленных полей, имени класса ... такого рода материал.Как бы вы реализовали базовое отражение в C++?

Я думал о разборе существующих исходных файлов, получал список объявленных полей & и переписывал каждый исходный файл, добавляя этот вид информации в каждый класс.

Что вы думаете об этом подходе? Я хотел бы сделать все с нуля, так как я думаю, что это отличная возможность учиться. Не могли бы вы предложить другие способы сделать это?

// OFFTOPIC: это как Qt?

+0

Не будет ли это стоить больше, чем RTTI, и что это даст? – Mark

+0

Жесткий. Вы не можете маршалировать компилятор для генерации метаданных, которые вам нужны из исходного кода. RTTI крайне неадекватен. Вам нужно будет написать собственный синтаксический анализатор языка C++. Это было сделано ... –

+0

@nobugz: Конечно, люди написали свои собственные сиквел C++. Это очень далеко не тривиально. C++ - очень простая реальная боль для синтаксического анализа. –

ответ

1

Если вы хотите изменить компилятор C++ или не зависит от расширений поставщика, вам понадобится куча макросов CPP, которые строят структуры данных.

3

Проверьте библиотеку Boost.Mirror. Это еще не принято в Boost, так что вам нужно будет download it из Boost Vault.

Библиотека все еще находится в стадии разработки, а документации недостаточно, но, изучая provided examples, вы можете достичь того, чего хотите.

EDIT:, если вы действительно хотите, чтобы разобрать ваш код самостоятельно C++, то, возможно, вам следует рассмотреть clang

+0

Ничего себе. Он выглядит таким кратким и простым в использовании. – Eric

+0

Вы саркастичны? – Manuel

+2

print_meta_data Eric

3

Я бы раскошелиться GCC.

2

Да, это так, как это делает Qt - за исключением того, что он не добавляет информацию самому классу, он создает новый класс, называемый метаклассом, который содержит статические данные о классе. Это по очевидным причинам.

Ни один подход на основе чистого C++ не обеспечит полностью автоматическое отражение - язык его не позволяет. Есть много попыток, в том числе Boost.Mirror и Boost.Reflection, но все они требуют добавления шаблонов к вашему источнику.

0

Возможно, вы можете использовать библиотеку typeinfo, с которой вы можете теперь стать классом объектов во время выполнения. Пример:

#include<iostream> 

#include<typeinfo> 
class A{}; 

int main() 
{ 
A a; 

std::cout<<typeid(a).name(); 

} 

Вы можете увидеть больше: http://www.cplusplus.com/reference/std/typeinfo/

[] `с

+0

Я не хочу использовать RTTI. – Geo

1

Вы можете найти gccxml стоит посмотреть. Он (например) преобразует this в this, что означает, что вам просто нужно разобрать XML вместо C++.

Там интересная SP & E paper, который описывает использование gccxml в сочетании с модифицированным линкером «обеспечивает Java-отражательную как функциональность приложений C++ в чистой и ненавязчивой манере».

1

Измените компилятор для создания статического метода GetClass, возвращая указатель на объект класса, описывающий класс, для каждого определенного класса.

Измените компилятор/компоновщик, чтобы вытащить нужные метаданные и заполнить их в специальных разделах/символах полученного исполняемого изображения - так же, как и отладочные символы.

GetClass будет использовать (чтение/загрузка/кеш?) Вышеуказанные метаданные.

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

1

C++ не поддерживает отражение. Усилия от повышения и RTTI довольно ограничены и наполовину испечены. Я бы не рекомендовал их.

Вы упомянули, что можете начать с scatch. Ну, вы можете написать лексику C++, используя lex/yacc, или ANTLR. Довольно много работы, но вы многое узнаете.

Если написать парсер - грозная задача для вас, есть и другие варианты получения метаданных класса. Microsoft имеет DIA SDK, который предоставляет информацию о символах. Doxygen может генерировать XML-файлы, которые можно проанализировать для получения имен полей, имен методов класса. У меня был некоторый успех, анализирующий XML-файлы doxygen.

Если вы работаете только с платформой Microsoft, жизнеспособным решением является использование библиотеки типов (TLB). Для этого требуется преобразовать класс в интерфейс в MS IDL. MIDL компилирует IDL в .tlb, и ваше приложение может загружать файл .tlb во время выполнения. Ваше приложение может получить почти всю информацию о классе через интерфейс, свойства и методы ITypeInfo.

+0

Ничего себе! Доксиген даже не передумал! Прохладный! – Geo

1

Следуйте за десятым законом Greenspun, и вам хорошо идти: просто реализуйте специальную, неформально указанную, с ошибкой, медленную реализацию половины Common Lisp. Выберите половину, которая поддерживает реализацию рефлексии. :)

Или вот идея:

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

Теперь, на C++, напишите библиотеку, содержащую функции и макросы, которые позволят вам поместить уникальный идентификатор, который будет быть скомпилированы в код для идентификации запуска функций, всех вызовов отражения, смещения EIP при вызовах отражения и т. д. Используйте встроенные макросы сборки в соответствующих местах, которые оставляют место, где это необходимо, с помощью NOP, чтобы приложить несколько инструкций, если вам нужно, как правило, сразу после Я БЫ. Кроме того, предоставляйте функции библиотеки моста, которые позволят функциональности отражения либо обрабатывать то, что она может встроить (например, получить адрес функции), либо делать вызовы в динамическую библиотеку, построенную на этапе после сборки.

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

В любом случае, я знаю, что не получил много кода, и на самом деле я намереваюсь начать проект по этому поводу, когда у меня будет достаточно свободного времени. Я имею в виду, что каждая маленькая часть должна быть очень простой, так как вы делаете это постепенно, каждая маленькая часть должна стать ясной, если вы будете следовать изложенным здесь инструкциям. Возможно, что некоторые из них на самом деле будут еще проще, чем я описал здесь, потому что это был худший сценарий. Вы даже можете уйти, даже не переписывая код на звонок рефлектора; просто размещение данных в соответствующих точках может позволить библиотеке вытягивать эти биты по мере необходимости без дополнительной информации.

Я очень рад, что вы спросили; Я сейчас очень занят, но если вы получите ночь бесплатно, я думаю, что это будет хороший старт в первой версии, и я буду рад, если смогу.

;)

+0

Ничего себе, я вижу, что прошло полтора года с тех пор, как вы задали этот вопрос, извините, что вам пришлось пройти без реального ответа так долго, но приятно знать, что я мог бы помочь. : D ♡ – shelleybutterfly

+0

Очень интересно и очень подробно. Я прочитаю об этом. Спасибо! – Geo

+0

ну, пожалуйста. :) имейте в виду, что, хотя я действительно думаю, что это можно заставить работать, это всего лишь дорожная карта. (Замечания о том, насколько это было бы легко, - это все слова в словах.) Но я верю, что, решаясь итеративно найти лучшее решение, это можно сделать. (Я также не уверен, что это проще, чем писать расширение на C++ и расширять gcc, чтобы скомпилировать его.) ... Звучит любопытно, как я это описал, но вроде бы: забудьте о C++, вы получая отражение, нравится вам это или нет ... :) – shelleybutterfly

Смежные вопросы