2009-08-30 4 views
17

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

+0

Я действительно сомневаюсь. – ChaosPandion

+4

Если вы хотите отражения, C и C++ - неправильные языки для вас. Это противоречит их философии «вы не платите за то, что не используете». – Crashworks

+0

Вы можете получить эффекты отражения, используя механизмы, не относящиеся к C/C++ langauges. См. Другие ответы. –

ответ

14

Отражение в целом является средством для программы для анализа структуры некоторого кода. Этот анализ используется для изменения эффективного поведения кода.

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

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

Необходим инструмент, который:

  • источник языка Анализирует текст
  • Строит абстрактные синтаксические деревья, представляющие каждую деталь программы. (Это полезно, если НРХ сохраняют комментарии и другие детали компоновки кода источника , такие как номера столбцов, буквенные значения поразрядной и т.д.)
  • строит символов таблицы, показывающие масштаб и значение каждого идентификатора
  • Может извлечь управление потоками из функций
  • Может extact поток данных из кода
  • Можно построить граф вызовов для системы
  • Можно определить, что каждый указатель указывает на-
  • Включает строительство пользовательских анализаторов с использованием выше п действует
  • Можно преобразовать код в соответствии с таким обычаем анализ (обычно путем пересмотра ASTS, которые представляют собой разобранный код)
  • может регенерировать исходный текст (включая расположение и комментарии) от В пересмотренном ASTS.

Используя такой механизм, один из них выполняет анализ на любом уровне детализации, а затем преобразует код для достижения эффекта, который будет выполняться во время выполнения. Есть несколько основных преимуществ:

  • Уровень детализации или количество анализа является предметом амбиций (например, не ограничивается тем, что во время выполнения отражение только может сделать)
  • Существует нет времени выполнения для достижения отраженного изменения в поведении
  • Применяемый механизм может быть общим и применяться на многих языках, а не , чем ограничиваться тем, что обеспечивает конкретная языковая реализация.
  • Это совместимо с идеей C/C++ о том, что вы не платите за то, что не используете. Если вам не нужно отражать, вам не нужна эта техника. И ваш язык не нужно иметь интеллектуальный багаж слабого отражения построен в.

Смотрите наш DMS Software Reengineering Toolkit для системы, которая может сделать все перечисленное выше для C, Java и COBOL, и большинство из них для C++.

+0

Что делать, если у вас нет исходного кода? – Crashworks

+0

Если у вас нет исходного кода, вам лучше надеяться, что отражение, которое отвечает на ваш конкретный вопрос, доступно в вашей системе программирования. Проблема OP была о C, которая вообще не имеет отражения. Если у вас есть система с отражением, например Java, вы часто обнаружите, что она не даст вам достаточно деталей; предоставляет ли Java имена и типы параметров функции, как запрошено ОП? Дело в том, что вам нужна мощная система для анализа кода, и большинство программных систем/языков не будут предоставляться. Итак, выйдите на улицу и получите инструмент, который * может *, без каких-либо исключений. –

+3

Вот еще один способ подумать.Отражение в langauges, которое связано с тем, сколько исходного кода компилятор желает оставить в своем объектном коде, чтобы включить отражение. Если он не сохранит * весь * исходный код, отражение будет ограничено в его способности анализировать доступные факты об исходном коде. –

5

На основе ответов на вопрос How can I add reflection to a C++ application? (Stack Overflow) и того факта, что C++ считается «надмножеством» C, я бы сказал, что вам не повезло.

Существует также хороший длинный ответ о why C++ doesn't have reflection (Stack Overflow).

+0

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

2

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

+0

Или, если вы обнаружите, что система полного отражения сама по себе немного сложна, вы можете использовать инструмент, предназначенный для анализа/преобразования кода, который имеет все необходимые механизмы. См. Другие ответы на этот вопрос. –

2
  1. Реализация отражения для C будет намного проще ... потому что C - простой язык.
  2. Существует несколько основных опций для программы-аналога, например, если функция существует, вызвав dlopen/dlsym - зависит от ваших потребностей.
  3. Есть инструменты для создания кода, который может изменять/расширять себя, используя tcc.
  4. Вы можете использовать вышеуказанный инструмент, чтобы создать свои собственные анализаторы кода.
+0

Вы можете найти параметры функции, скажем, грех, используя dlopen/dlsym? и какие хорошие анализаторы кода? – adk

+1

«Вы можете найти параметры функции« Нет, просто такой символ существует. – Artyom

7

любые трюки вокруг него? Какие-нибудь советы?

Компилятор, скорее всего, будет генерировать «файл символов отладки», который отладчик может использовать для отладки кода. Компонент может также генерировать «файл карты».

Трюк/подсказка может быть сгенерирована, а затем читать эти файлы.

3

Мне нужно отражение в связке struct s в проекте на C++.
Я создал файл xml с описанием всех этих структур - к счастью, типы полей были примитивными типами.
Я использовал шаблон (не C++ template) для автоматического создания class для каждого struct наряду с методами setter/getter.
В каждом class Я использовал карту для сопоставления имен строк и членов класса (указатели на элементы).

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

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

+0

Итак, вы использовали специальный подход для достижения эффекта желания. Если это сработает для вас, отлично. Структурированный подход к выполнению того, что вы хотели, позволил бы вам пропустить XML-описание этих структур, закодированное вручную, и «отразить» фактические данные самих объявлений структур. См. Другие ответы на этот вопрос. –

+0

Просто то, что я имел в виду, собираюсь написать скрипт PHP, анализирующий мои .cpp-файлы, которые затем выгружают код C++, что делает отражение. Мне нужно использовать C-структуры с помощью механизма сценариев. – lama12345

1

Я знаю из следующих вариантов, но все приходят по стоимости и много ограничений:

  • Использование libdl (#include <dfcln.h>)
  • Вызов инструмент, как objdump или nm
  • разбирает объектные файлы (используя соответствующую библиотеку)
  • Привлекайте парсер и генерируйте необходимую информацию во время компиляции.
  • «Злоупотребление» компоновщиком для создания символьных массивов.

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

Использование libdl (#include <dfcln.h>) (POSIX)

Если вы на среде POSIX, немного отражения может быть сделано с помощью libdl. Плагины разработаны таким образом.

Использование

#include <dfcln.h> 

в исходном коде и связь с -ldl.

Тогда у вас есть доступ к функциям dlopen(), dlerror(), dlsym() и dlclose(), с которым вы могли бы загружать и доступ/запускать общие объекты во время выполнения. Однако это не дает вам легкого доступа к таблице символов.

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

Запуск nm или objdump

Вы можете запустить nm или objdump, чтобы показать таблицу символов и разобрать вывод. Для меня nm -P --defined-only -g xyz.o дает хорошие результаты, а синтаксический анализ результатов тривиален. Вас будет интересовать первое слово каждой строки, которое является именем символа, и, возможно, второе, которое является типом раздела.

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

objdump, nm или аналогичные инструменты также часто доступны вне среды POSIX.

Синтаксический объект файлы самостоятельно

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

Вовлекая Parser

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

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

«вольность» компоновщик для создания символов массивов

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

Я здесь описал N-Dependency injection in C - better way than linker-defined arrays?, как это работает.

Но будьте осторожны, это зависит от множества вещей и не очень портативен. Я только пробовал это с GCC/ld, и я знаю, что он не работает со всеми компиляторами/линкерами. Кроме того, почти гарантировано, что удаление мертвого кода не будет определять, как вы называете это, поэтому, если вы используете исключение мертвого кода, вам нужно будет добавить все отраженные символы в качестве точек входа.

Ловушка

Для некоторых механизмов, удаление неиспользуемого кода может быть проблемой, в частности, когда вы «злоупотребление» компоновщик генерировать символ массивы. Его можно обойти, указав отраженные символы как точки входа в компоновщик, и в зависимости от количества символов это может быть ни хорошим, ни удобным.

Заключение

Объединение nm и libdl фактически может дать неплохие результаты. Комбинация может быть почти такой же мощной, как уровень Reflection, используемый JUnit 3.x в Java. Необходимый уровень отражения достаточен для реализации модульной тестовой среды JUnit 3.x для C, включая обнаружение тестового случая по соглашению об именах.

Вовлечение парсера - это больше работы и ограничено предметами, которые вы скомпилируете самостоятельно, но дает вам максимальную власть и свободу. Уровень отражения может быть достаточным для реализации модульной тестовой среды JUnit 4.x для C, включая обнаружение тестовых случаев аннотациями. AceUnit - это единая тестовая среда для C, которая делает именно это.

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

И, конечно же, вы можете комбинировать все подходы, чтобы сшить кусочки и куски, пока они не соответствуют вашим потребностям.

2

Советы и рекомендации всегда существуют.Взгляните на библиотеку Metaresc https://github.com/alexanderchuranov/Metaresc

Он предоставляет интерфейс для объявления типов, который также будет генерировать метаданные для этого типа. На основе метаданных вы можете легко сериализовать/десериализовать объекты любой сложности. Из коробки вы можете сериализовать/десериализовать XML, JSON, XDR, Lisp-подобную нотацию, нотацию C-init.

Вот простой пример:

#include <stdio.h> 
#include <stdlib.h> 
#include <math.h> 

#include "metaresc.h" 

TYPEDEF_STRUCT (point_t, 
       double x, 
       double y 
       ); 

int main (int argc, char * argv[]) 
{ 
    point_t point = { 
    .x = M_PI, 
    .y = M_E, 
    }; 
    char * str = MR_SAVE_XML (point_t, &point); 
    if (str) 
    { 
     printf ("%s\n", str); 
     free (str); 
    } 
    return (EXIT_SUCCESS); 
} 

Эта программа будет выводить

$ ./point 
<?xml version="1.0"?> 
<point> 
    <x>3.1415926535897931</x> 
    <y>2.7182818284590451</y> 
</point> 

библиотека работает для последней НКУ и лязгом.

0

Просто сделайте любой вид таблицы, дерева, связанного списка или любой другой коллекции, удобной для управления или считающейся эффективной. Добавьте ключ, будь то строка, тип/идентификатор combo или whatnot и укажите адрес функции или структуры. Супер наивный вариант отражения может быть совокупность следующих действий:

struct reflectable{ 
    size_t size,id,type; // describes payload 
    char* name; 
    void* payload; 
} 

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

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