Приветствую Вас, Гость
Главная » Статьи » Мои статьи

Архитектура QtE
QtE - простая библиотека для использования в языках D ( http://dlang.org/ ) и Forth spf 4.20. Cама библиотека предоставляет доступ к небольшому, ограниченному набору виджетов библиотеки Qt. Работает и в Windows и в Linux. 

Cама QtE состоит из модуля поддержки языка (qte.f для Forth и qte.d для D) и DLL для связи с самой QT.

Схема следующая для форта:

  нашаПрограмма <== qte.f <=== qte.dll (so) <=== Qt

соответственно для D:

  программаD <== qte.d <=== qte.dll (so) <===Qt


Для обоих языков qte.dll (so) одинакова.

1 - Установка на компьютер.

Для установки главное обеспечить правильную работу qte.dll. Для Windows все просто, ставим нашу dll в каталог с программой и можно работать. Для Linux сложнее. Необходимо не только скопировать qte.so но и прописать к ней доступ. Обычно для этого используются переменная окружения LD_LIBRARY_PATH. Для текущего каталога надо дать такую команду в шелл: LD_LIBRARY_PATH=`pwd`; export LD_LIBRARY_PATH

Библиотеки ищутся по путям. Если пути правильно настроены то поиск происходит нормально. В самих модулях qte.d и qte.f доступ к библиотекам задан относительным путем.
Следует обратить внимание. что в Linux может возникать хитрая ошибка. Qt имеет несколько стилей при отображении. такие как motif, cleanlook и т.д. Так вот выяснилось. что не все эти стили может поддерживать конкретная версия Qt и как следствие не всегда наша программа работает в конкретной настройке Qt. Например, у меня в Linux в KDE стояла тема оксиген, в результате программа падала из за ошибок сегментации. Cмена стиля с оксигена на motif решила все проблемы.

2-компиляция qte.dll (so)

Все необходимые файлы лежат в соответствующей папке. Набор файлов а это qte.hpp и qte.cpp одинаков для W и L (Windows Linux). В W используется компилятор mingw входящий в состав sdk по Qt. В L используется g++. Для правильной компиляции надо отредактировать файл qte.hpp Там определены два #define. Один для W другой для L. Все меняется просто через установку и снятия соответствующего комментаря на нужном #define. После компиляции получается соответственно либо DLL либо SO.

3-работа с самой qte.

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

Это конечно не QtD и не Lazarus и конечно не Qt. QtE маленькая, всего то около одной тысячи строк. Зато простая сборка и работа с самой библиотекой. Я рассматриваю ее как средство изучения языка форта или ди. Просто писать консольные примеры не интересно. а тут сразу современный кросплатформенный интерфейс. Да, вот еще момент. Дело в том что в L уже стоит по умолчанию Qt, если вы используете KDE. Для W придется копировать набор dll. Минимально необходимый набор это QtCore.dll и QtGui.dll. Возможно могут понадобится еще некоторые DLL, зависящие от конкретной версии Qt.

4 — Подключаем QtE к D. 

Для подключения модуля в D программе надо вставить оператор:

import qte

для spf 4-20 вставить строку:

REQUIRE qte ~mgw/qte.f

оба этих модуля обращаются к одной и тойже qte.dll ( so ). Всякая программа на Qt состоит из двух обязательных операторов. Это:

QApplication app(argc, argv);
...... текст программы .....
app.exec();

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

Разберем подробнее как осуществляется инициализация в рамках наших модулей.

Для форта это:

fQApplication NEW a1 // создание класса форта
VARIABLE argc
if=W TRUE GetCommandLineA ASCIIZ> args SWAP argc ! argc a1.adrQApplication {{ QtE pFunQt_0 }} DROP
if=L TRUE ARGV ARGC argc ! argc a1.adrQApplication {{ QtE pFunQt_0 }} DROP
различие для W и L связаны с различным способом подготовки входных параметров. Фактически тут происходит вызов реального C++ конструктора.

Посмотрим как это сделано для D:

QApplication app = new QApplication; // Создали, но конструктор не вызван

                                                             // Связанно с тем, что вызов конструктора QApplication                    
                                                             // должен быть произведен в main(), иначе в Linux ошибка ....
(app.adrQApplication())(cast(void*)app.bufObj, &Runtime.cArgs.argc, Runtime.cArgs.argv);

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


Теперь когда мы сделали инициализацию. нам остается только вызвать цикл обработки сообщений. Это уже просто.
Для ди:
app.exec();

Для форта:
a1.exec


5- Работа с объектами.

Важное замечание. QtE не работает самостоятельно с объектами C++ она только хранит ссылки на такие объекты (исключение QAapplication). В связи с этим работа любого класса в qte разбивается на два этапа. 1-Создать объект qte, 2-инициализировать объект вызвав конструктор C++ с параметрами, используя метод create.

Почти всегда метод create имеет параметры для аналогичного конструктора C++. Правда такое замечание больше касается форта, так как на ди иногда удается совместить одновременный вызов конструктора ди и с++. Еще одно важное замечание. Вы постоянно будите встречать в примерах параметр QtObj. Его задача выдать непосредственную ссылку на объект C++. Особенно это видно в модулях qte.d и qte.f

6 - вызов методов C++

Рассмотрим следующую конструкцию из qte.d:

pFunQt[1] = GetPrAddres(bGui, hQtGui, "_ZN12QApplication4execEv");

 расшифровывается она так. Найти адрес процедуры в QtGui.dll (so) который имеет символьную метку _ZN12QApplication4execEv и помести этот адрес в ячейку массива номер 1. Как видно из имени, которую автоматом формирует C++ это процедура нам знакома. это QApplication.exec(); Мы забираем этот адрес непосредственно из dll, фактически работая за линковщик.

Выполнение:

return (cast(t_Qapplication_Exec)pFunQt[1])(cast(void*)bufObj);

Типизируй указатель pFunQt[1] как функцию и вызови её с параметром bufObj. Это прямое моделирование метода exec(); Параметр, это указатель на данные объекта. Так осуществляем вызов методов.

Категория: Мои статьи | Добавил: mgw (30.09.2013) E
Просмотров: 624 | Комментарии: 1 | Теги: qt, forth, dlang, qte | Рейтинг: 0.0/0
Всего комментариев: 1
1 Гость  
Интересно, но оформление не очень

Имя *:
Email *:
Код *: