Форум программистов, компьютерный форум, киберфорум
C++ Builder
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.73/11: Рейтинг темы: голосов - 11, средняя оценка - 4.73
872 / 448 / 35
Регистрация: 25.10.2011
Сообщений: 910
1

Динамическое создание стандартных коммпонентов без RTL и пакетов в DLL.

12.11.2011, 22:34. Показов 2301. Ответов 7
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Доброе время суток.Собственно сабж, есть динамическая библиотека, в которой посылая указатель на форму, создается некий компонент, к примеру TButton. Все отлично, но вдруг моя рука дрогнула и я отключил RTL и наказал компилятору брать все пакеты с собой. И после этого при вызове функции получаю либо кучу ошибок адресации, либо кнопка просто не отображается(при отключении ParentFont). Провозился с этим моментом кучу времени, но так и не понял, возможно ли подобное в вышеперечисленных условиях.

Из последних мучений всевозможных упрощений, имею следующее.

Функция создания кнопки:
C++
1
2
3
4
5
6
7
8
9
extern "C" __declspec(dllexport) int __stdcall MyCreate(const int address)
{
TButton *MyButton = new TButton((TWinControl*)address);
MyButton->Left = 20; MyButton->Top = 20; 
MyButton->Width = 100; MyButton->Height = 20;
MyButton->Name = "MyButton1";
MyButton->Caption = "Hello world!";
MyButton->Parent = (TWinControl*)address;
};
Вызов функции:
C++
1
2
3
4
5
6
7
typedef int (__stdcall *TProc) (int);
//...
HMODULE DLL = LoadLibrary("Project1.dll");
TProc Proc = (TProc) GetProcAddress(DLL,"MyCreate");
int ButtonAddress = Proc((int)this);
//...
FreeLibrary(DLL);
Пробовал передавать тип "TForm*" и "TForm*&", а так же и "TApplication*" и через него получать форму, но результат все равно тот же. При этом, если не не указывать родителя кнопки, могу спокойно в приложении получить всю информацию о кнопке, что я указал.
Есть у кого-нибудь мысли на этот счет?

Добавлено через 14 часов 31 минуту
Собственно ап. Можно пример и с формой, лишь бы это было в форме MDI или просто родителем указывается необходимая форма. Главное условие избежать ShowModal.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
12.11.2011, 22:34
Ответы с готовыми решениями:

Поменять путь поиска пакетов rtl, vcl
Привет всем. Интересует вопрос как приложение заставить искать нужные BPL (rtlxx.bpl и vclxx.bpl)...

Разработка приложений с использованием стандартных и дополнительных компонентов. Динамическое создание компонентов.
Здравствуйте! Помогите мне, пожалуйста. Условие задачи состоит в следующем: из списка выбираю...

Создание таблицы без использования стандартных элементов управления
Как мне создать динамически таблицу на форме, не используя DataGridView и GridControl, что бы...

Динамическое создание VCL-объектов из dll
Тренируюсь использовать динамически dll. Пока все вроде получается, но есть одна неясность. Задача...

7
1365 / 732 / 67
Регистрация: 28.01.2011
Сообщений: 2,064
12.11.2011, 23:31 2
здесь
здесь
и здесь
0
872 / 448 / 35
Регистрация: 25.10.2011
Сообщений: 910
12.11.2011, 23:36  [ТС] 3
Samrisbe, спс конечно, но меня интересует динамическое создание компонентов в модуле (DLL), после чего их дальнейшее использование в приложении загрузившим модуль. Еще недельку покопаюсь, если ничего не найду, значит придется использовать MEMMGR.LIB.
0
1365 / 732 / 67
Регистрация: 28.01.2011
Сообщений: 2,064
12.11.2011, 23:57 4
Попробуй поиск по форуму недавно точно обсуждалась тема подходящая под твой вопрос.
0
1123 / 794 / 101
Регистрация: 01.02.2011
Сообщений: 1,878
Записей в блоге: 1
13.11.2011, 00:06 5
В инете пишут, что dll нужно компилировать с run time packages, иначе полезут ошибки.
Один пишет:
Весь вечер бился с выявлением причины возникновения ошибки "Cannot assign a TFont to a TFont"
Ему отвечают:
В Exe TFont находится по одному адресу, в DLL по другому. Операция IS сравнивает адреса, если не совпадают, значит TFont-ы разные.
1
872 / 448 / 35
Регистрация: 25.10.2011
Сообщений: 910
13.11.2011, 00:16  [ТС] 6
Цитата Сообщение от Samrisbe Посмотреть сообщение
Попробуй поиск по форуму недавно точно обсуждалась тема подходящая под твой вопрос
Не канает с поставленными условиями.

Цитата Сообщение от kzru_hunter Посмотреть сообщение
В инете пишут, что dll нужно компилировать с run time packages, иначе полезут ошибки.
Ну мы с вами вроде тоже не на лавочке сидим Вот меня и интересует как от этого избавится. Не всегда такскать с собой библиотеки выгодно. Нужно еще попробовать создание производных классов.
0
1123 / 794 / 101
Регистрация: 01.02.2011
Сообщений: 1,878
Записей в блоге: 1
13.11.2011, 00:23 7
С другого форума:
DLL и VCL классы
Можно то можно, но путем проб и ошибок, потому как шибко многое синхронизировать придется, а потом код получиться в сумме больший, так как все придется линковать и в хост и в длл.
Вот тебе для размышления:
Q: Я разделил свою программу на основной Exe и Dll. после этого все стало
глючить.
(Возможные симптомы: программа отображается на линейке 2 раза, появляются
загадочные сообщения типа "Cannot assign TFont to TFont", базы данных спрашивают
пароль 2 раза(один раз для dll и один раз для exe), происходят загадочные Access
Violation )

Вы неправильно скомпоновали вашу dll. Для того чтобы все заработало нужно
скомпилить и Exe и Dll c dynamic rtl и runtime packages. Проверьте так же что
все Packages перечислены в списке RP. Т.е. может быть такая ситуация,
что RP включены, но какой нибудь из них в списке пропущен и используется
статически.

Многим людям лень искать какие dll нужны поэтому они все линкуют
в свои exe и dll. Я категорически рекомендую не делать этого.
Уже если вы разделили прогу на exe dll то используйте все остальное
тоже в dll

Несколько причин последовать этому совету:

Причина 1.
Вы все наверняка работали с чужими dll. Хотя бы вызывая функции Windows.
Вы обратили внимание что все строки в них передаются с помощью char*.
Кроме того когда вы например вызываете функцию GetComputerName,
то она не просто возвращает строку, а заставляет вас передать указатель
на буфер и его длину. Это сделано для того чтобы не было таких вещей
чтобы память выделялась в одном модуле а стиралась в другом. Потому как
это некорректно.
В каждом модуле есть такая штука как memory manager которая
выделяет память, освобождает ее и ведет список свободных и занятых блоков.
Так вот когда у вас exe и dll скомпилены без dynamic rtl то получается что у вас
2 разных memory manager-а. Как вы думаете что будет если вы попросили у одного
из них память, а потом попросили другого его стереть?
Я думаю ничего хорошего не получится. Можно конечно дать совет не делать
так. Но учтите что при передаче AnsiString в качестве параметра память
выделяется в вызывающей функции, а уничтожается в вызваной.
Таким образом получается, что нельзя вызывать из dll функции с
параметром AnsiString.

Как это лечится.
1) Достаточно включить use dynamic rtl и у вас получится один менеджер
памяти в специальной dll borlndmm.dll
2) Можно не включать, а сделать как написано в большом комментарии в начале
новосозданной dll. Там рекомендуют включить в проект MEMMGR.LIB. Но в этом
случае все равно будет использоваться borlndmm.dll.
Легче сделать как сказано в пункте 1.

Причина 2.
Вы знаете о существовании глобальных переменных Application, Session и т.п?
А знаете где они объявлены? Соответственно в Forms и Dbtables. А догадываетесь
что будет если подключить эти unit-ы статистически к exe и dll? Правильно у вас
будет по 2 копии этих переменных, одна в одном модуле другая в другом.
Именно из-за этого появляются такие эффекты как двойное название приложения
в линейке задач (чего вы удивляетесь, у вас на самом деле 2 приложения) и
то что пароли к базе данных(имеется ввиду BDE)спрашиваются 2 раза
(у вас 2 сессии, один раз введите пароль для одной и один для другой.
Кстати соединений с БД у вас тоже будет 2).

Как это лечится.
Ну например в случае раздвоения на линейке задач можно передать в dll
Application->Handle из exe и присвоить его местному Application->Handle.
Для Session это наверное тоже как нибудь лечится. Но самый простой
путь это включить Runtime Packages. Тогда у вас будет только одна
копия переменных в отдельном Bpl

Причина 3.
Вы не задумывались как работают операции динамического определения типа.
dynamic_cast в C++ и is/as в Pascal? Они сравнивают указатель на виртуальную
таблицу. Что будет если один и тот же компонент есть в 2 модулях? Правильно,
у него будет 2 виртуальные таблицы. Что будут делать операторы определения
типа когда определяют тип компонента из другого модуля пытаясь сравнить его
vptr с vptr который должен быть в этом модуле? Правильно, они скажут что это
разные компоненты. Отсюда всякие извраты типа Cannot assign TFont to TFont.
Кроме того например Toolbar2000 будучи пристыкован статически не опознает
свои собственные Toolbar-ы из другого модуля и отказывается их пристыковывать.
Есть информация что IBX в таком состоянии просто глючит. Некоторые компоненты
все таки ведут себя вполне прилично, но вы готовы рисковать работоспособностью
программы чтобы выяснить что тот компонент который вы используете именно такой?

Как лечить. Те классы которые не наследуются от TObject определяется
правильно ( Magic! ). С наследниками TObject сделать ничего нельзя.
Единственный выход это включить Runtime Packages.

Причина 4.
При всем этом суммарный объем кода увеличивается т.к. один и тот же код
содержится и в dll и в exe.

Мораль.
Либо не используйте dll вообще либо делайте их с dynamic rtl и
runtime packages. Обычно эти опции отключают чтобы не искать какие
dll и bpl еще нужны. Но поверьте это ничто по сравнению с тем количеством
проблем которые вас ожидают если вы не воспользуетесь этим советом.
1
872 / 448 / 35
Регистрация: 25.10.2011
Сообщений: 910
13.11.2011, 00:31  [ТС] 8
Цитата Сообщение от kzru_hunter Посмотреть сообщение
В Exe TFont находится по одному адресу, в DLL по другому. Операция IS сравнивает адреса, если не совпадают, значит TFont-ы разные.
А вот за это большое спасибо. Значит тут 2 варинта, перенаправить DLL или работать отрешиться от поставленных условий.
1
13.11.2011, 00:31
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
13.11.2011, 00:31
Помогаю со студенческими работами здесь

Динамическое создание элементов с использованием DLL
Доброго всем времени суток! Можно ли сделать так, чтобы при вызове определенной функции (на...

Почему в стандартных репозиториях не самые свежие версии пакетов?
Здравствуйте. Установил Linux Mint 15 (последнюю версию). Сразу после установки и обновления...

Какая плата лучше? SUS M4A785TD-V EVO (RTL) или ASRock M3A790GXH/128M (RTL)?
Выбираю между...

Создание Hook-ов без dll
Можно ли создать hook без dll? если да, то скиньте код)


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
8
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru