Главная » Статьи » Мои статьи |
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 программе надо вставить оператор: для spf 4-20 вставить строку: REQUIRE qte ~mgw/qte.f оба этих модуля обращаются к одной и тойже qte.dll ( so ). Всякая программа на Qt состоит из двух обязательных операторов. Это: QApplication app(argc, argv); ...... текст программы ..... app.exec(); Это минимальная программа на Qt в синтаксисе С++. Первая строка это инициализация. Вторая цикл опроса графических сообщений. Между этими строками мы должны подготовить наши виджеты, ну а когда начнется цикл опроса сообщений мы увидим результат нашей работы, а именно графическую программу. Разберем подробнее как осуществляется инициализация в рамках наших модулей. Для форта это: 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; // Создали, но конструктор не вызван // должен быть произведен в 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(); Параметр, это указатель на данные объекта. Так осуществляем вызов методов. | |
Просмотров: 1064 | Комментарии: 2
| Теги: |
Всего комментариев: 1 | ||
| ||