6

Компилятор с Java в “родной” код - “на коленках”?

Я на работе почти доделал свой долбаный отчет, и решил устроить себе маленький отдых. В блог долго ничего не писал, поскольку хотелось выдать чо-то такое СУРЬЕЗНОЕ и ИНТЕРЕСНОЕ, в результате ни того, ни другого родить не удалось.

Как обещал в предыдущем посте, объясню, для чего могут понадобиться вещи, описанные мной в постах о SmartPointers и исключениях. Дело в том, что мне нравится Java, пожалуй, даже слишком. Не буду заниматься тут ее рекламой, поскольку сравнение языков - дело неблагодарное. Но Java-программа не может выполнятся без окружения(JRE), а дистрибутив JRE весит 17 Мб. Не хухры-мухры, даже если вы не на диалапе сидите. Моя голубая мечта - компилятор Java-программ в "родной" исполняемый код той платформы, которую я использую. Увы, GNU Java слишком урезана, что бы ее можно было использовать, да и одна важная вещь - шаблоны там пока не поддерживаются. Разжиться такой штукой, как Excelsior Jet мне совсем не по карману.
Посему стали посещать такие мысли - а может, просто преобразовать программу, написанную на Java в прогу на C++? Что в C++ такого, чего нет в Java? На первый взгляд мне показалось, что все очень просто, ведь C++ - охрененно мощный язык. Там есть.... куча всего нужного. И не очень.
Короче, разворачивание стека вызовов, как в Java, на C++ эмулировать просто. Простейший сборщик мусора "для бедных" - тоже. Как мне кажется, можно даже сравнительно просто сделать дефрагментацию кучи. Если кому интересно, каким образом - постараюсь изобразить реализацию. В тупик меня поставил Reflection API. Я всегда пытаюсь избегать категоричных утверждений, но похоже, что Reflection API нельзя эмулировать с помощью той RTTI, которая есть в C++ на сегодняшний день. В черновике стандарта C++ от 19.10.2005 класс type_info описан так:

namespace std{
class type_info {
public:
virtual ~type_info ();
bool operator ==( const type_info & rhs ) const ;
bool operator !=( const type_info & rhs ) const ;
bool before ( const type_info & rhs ) const ;
const char * name () const ;
private :
type_info ( const type_info & rhs );
type_info & operator =( const type_info & rhs );
};
}

Видно, что за просто так вы вряд ли что-то получите, окромя названия типа в виде текстовой строки. Не говоря уже о таких вещах, как получение различных конструкторов типа и их использования для создания экземпляров или получения списка доступных полей и методов. Короче, нужно что-то такое свое ваять, дабы получить требуемый эффект. Причем этот стандарт не требует, что бы функция const char* name() возвращала уникальную для каждого типа строку.
В последнем стандарте (черновик C+0X от 4.10.2008) ситуация стала получше. Там класс type_info описан следующим образом:

namespace std {
class type_info {
public:
virtual ~type_info();
bool operator==(const type_info& rhs) const;
bool operator!=(const type_info& rhs) const;
bool before(const type_info& rhs) const;
size_t hash_code() const throw();
const char* name() const;
type_info(const type_info& rhs) = delete; // cannot be copied
type_info& operator=(const type_info& rhs) = delete; // cannot be copied
};
}

Появилась, к счастью, функция size_t hash_code(), про которую английским по белому накорябано:
"Returns: an unspecified value, except that within a single execution of the program, it shall return the same value for any two type_info objects which compare equal.
Remark: an implementation should return different values for two type_info objects which do not compare equal".
То бишь, если два объекта класса type_info по результатам сравнения оказались не равны, эта функция для разных объектов должна возвращать разные значения, а если равны - то одинаковые.
Сначала хотел закончить этот пост пессиместическим резюме о том, что мои надежды рухнули, эмулировать Reflection API на C++ не получится (помидоры завяли, солнце не светит, и т.п). Но некоторые весчи меня обнадеживают. Так, класс type_info поддерживается библиотекой, и возможно, я смогу его переопределить и добавить в него функцию hash_code. Кроме этого, я заглянул в исходники самого Java Reflection API. Похоже, реализация его сделана в основном на Java, а не зашита полностью в виртуальную машину. Так что есть что почитать, о чем подумать, авось какие мысли появятся.

6 коммент.:

Unknown комментирует...

Сначала хотел закончить этот пост пессиместическим резюме о том, что мои надежды рухнули, эмулировать Reflection API на C++ не получится (помидоры завяли, солнце не светит, и т.п).

Не понятно почему такие мысли. Зачем вообще пользоваться C++ RTTI, а не построить своё?

Да в С++-ном сорце полученном из Java-вского будет некоторая дополнительная логика, связанная с самодельным RTTI, но это ведь не страшно, вам же руками этот С++-ный файл не надо будет править =)

Lotrex комментирует...

Да в С++-ном сорце полученном из Java-вского будет некоторая дополнительная логика, связанная с самодельным RTTI

Хочется, что бывсе это было максимально простым. В идеале - для каждого Java-класса создавать дополнительный C++-класс из готового шаблона:

//Шаблон ClassRTTI - эмуляция класса java.lang.Class
class ClassRTTI<T>
{
.....
}

class Foo
{
.....
}

//Использование Reflection API
ClassRTTI<Foo> *foodescr = new ClassRTTI<Foo>();
ClassRTTI<Foo>::Constructors fooconstr = foodescr->getConstructors();

Хочется сделать такую программулину (создающую исходник на C++) максимально простой. Чтобы не генерировать для каждого класса некий класс, содержащий всю RTTI, а использовать шаблон ClassRTTI<T> единый для всех классов.
Уфф, написал немного сумбурно, но надеюсь, понятно.

Unknown комментирует...

Не пойдёт, как скажем по T оффсеты полей узнать или объявленные в нём методы?

В pure C++ такой возможности нет.

Lotrex комментирует...

Не пойдёт, как скажем по T оффсеты полей узнать или объявленные в нём методы?

В pure C++ такой возможности нет.

В этом-то вся проблема :((
Поэтому все классы, которые мы будем подставлять вместо T, должны поддерживать некий интерфейс, позволяющий эту информацию узнать.
В каждом классе, для которого мы будем использовать RTTI необходимо
реализовать(сгенерировать автоматически) функции этого интерфейса.
Проблема в том, как построить такой интерфейс, чтобы объем генерируемого кода, реализующего этот интерфейс был минимален, а его логика - предельно проста.

Unknown комментирует...

Ну я собственно это и имел ввиду, под собственным RTTI =)

日月神教-任我行 комментирует...
Этот комментарий был удален администратором блога.

Отправить комментарий