Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2006.07.09;
Скачать: [xml.tar.bz2];

Вниз

И снова форма в dll : инициализация   Найти похожие ветки 

 
parovoZZ ©   (2006-05-23 00:36) [0]

Здарова

У меня в dll две формы - одна рабочая (с визуальными компонентами), а вторая DataModule. Вот её то и не получается инициализировать (рабочая с компонентами в данный момент не нужна). Т.е. нужны компоненты ADOcommand, ADOConnection и ADODataSet. Делаю следующее:
unit DF;

interface

uses
 Windows, Classes, DB, ADODB, Forms;

type
 TDMd = class(TDataModule)
   ADOConnection: TADOConnection;
   ADOCmd: TADOCommand;
   ADODS: TADODataSet;
 private

 public
   { Public declarations }
 end;

//procedure DllEntryPoint (Reason : DWord);
procedure InitData; stdcall;

var
 DMd: TDMd;

implementation

{$R *.dfm}

procedure InitData; stdcall
begin

 DMd := TDMd.Create (Application);

end;

{
initialization
//if (DllProc = nil) then
 begin
  DllProc := @DllEntryPoint;
  DllEntryPoint (DLL_PROCESS_ATTACH);
 end;
finalization    }

exports
InitData name "InitData";

end.


Так вот на строчке   DMd := TDMd.Create (Application); возникает ошибка EOleSysError with message "Не был произведён вызов CoInitialize". Чего я такого не сделал?
Да, вызывающий exe написан на апях.


 
DrPass ©   (2006-05-23 00:48) [1]

Наступил на грабли VCL - она в общем случае не предназначена для использования в DLL. В данном случае в модуле ComObj не выполнилась секция инициализации (это не ошибка, это фича :-). В этой секции кроме всего прочего производился вызов CoInitialize - необходимое условие для работы основанных на COM компонент, например, ADO


 
evvcom ©   (2006-05-23 08:32) [2]

Ну так произведи вызов CoInitialize перед Create. Примеров в VCL куча, ты клавишами Ctrl+F пользоваться умеешь?


 
parovoZZ ©   (2006-05-23 09:14) [3]

Ладно, будем попробовать.


 
isasa ©   (2006-05-23 10:53) [4]

Собирался добавить, так добавь. :)

procedure DLLEntryPoint(Reason: Integer); // stdcall;
begin
 case Reason of
   DLL_PROCESS_DETACH: //= 0;
 CoUninitialize;
   DLL_PROCESS_ATTACH: //= 1;
       CoInitializeEx( nil, COINIT_MULTITHREADED);      // MTA
       // или CoInitializeEx( nil, COINIT_APARTMENTTHREADED);  // STA
 end;
end;
из MSDN
CoInitializeEx provides the same functionality as CoInitialize and also provides
a parameter to explicitly specify the thread"s concurrency model.
The current implementation of CoInitialize calls CoInitializeEx and specifies
the concurrency model as single-thread apartment.
Applications developed today should call CoInitializeEx rather than CoInitialize.

И что такое Application в DLL? Оно такое, как в EXE? Выставь, хотя бы
Application(из DLL).Handle:=Application(из EXE).Handle


 
parovoZZ ©   (2006-05-23 20:14) [5]

Exe у меня на апях, там нет никакого Application. Есть просто MainHandle.


 
parovoZZ ©   (2006-05-23 20:38) [6]

А где объявлена эта функция? на мсдн написан objbase, но у меня нет такого.


 
isasa ©   (2006-05-23 21:39) [7]

{$Delphi}\Source\Rtl\Common\ComObj.pas


 
isasa ©   (2006-05-23 21:43) [8]

parovoZZ ©   (23.05.06 20:14) [5]

Exe у меня на апях,

Если есть
uses ... Forms,...
то имеется :)

В общем, идея такая, Application.Handle в DLL, заполняется ручками ...


 
parovoZZ ©   (2006-05-23 22:53) [9]

Ура, заработало.


> Если есть uses ... Forms,...то имеется :)


Если я говорю, что Api, значит Api. Ну нравятся мне exe весом 50 кило.

А смысл заменять у Application Handle?


 
isasa ©   (2006-05-23 23:42) [10]

А подумать?

...
DMd := TDMd.Create (Application);
...


 
DrPass ©   (2006-05-23 23:51) [11]


> А смысл заменять у Application Handle?

Ровным счетом никакого. Сообщения-то все равно будут приходить в оконную функцию, объявленную в основной программе, а не в Application.
А в том Application, которое объявлено в DLL, вообще не создается ни оконная функция, ни дескриптор (это тоже фича, начиная с D6)


 
DrPass ©   (2006-05-23 23:52) [12]


> isasa ©   (23.05.06 23:42) [10]
> А подумать?
>
> ...
> DMd := TDMd.Create (Application);

И причем тут дескриптор Application?


 
isasa ©   (2006-05-23 23:54) [13]

На сон.
Если не морочить голову с Application и освобождать ресурс ручками
DMd.Free
пиши
DMd := TDMd.Create (nil);


 
isasa ©   (2006-05-24 00:01) [14]

DrPass ©   (23.05.06 23:52) [12]
И причем тут дескриптор Application?


А хорошо ли, в качестве родителя, указывать проблемный объект?


 
DrPass ©   (2006-05-24 00:05) [15]


> isasa ©   (24.05.06 00:01) [14]

А он абсолютно непроблемный. В том же и смысл отсутствия оконной функции и дескриптора в Application в DLL, чтобы их корректно разруливать. Кстати, в версиях D5 и более старых действительно нужно было их синхронизировать... только более жесткими методами - DLL_Application:= EXE_Application. В данном же случае единственный смысл этого объекта - общий родитель для форм и модулей в DLL.


 
isasa ©   (2006-05-24 00:33) [16]

Тоесть, для DLL корректно
Application.Terminate
?


 
isasa ©   (2006-05-24 00:38) [17]

Наверно непонятно написал.
Имел ввиду следующее. Освобождаем ресурсы проще?

procedure DLLEntryPoint(Reason: Integer); // stdcall;
begin
case Reason of
  DLL_PROCESS_DETACH: //= 0;
    CoUninitialize;
    Application.Terminate;


 
DrPass ©   (2006-05-24 01:06) [18]


> isasa ©   (24.05.06 00:38) [17]

А здесь вообще Application.Terminate не нужно. Application.Terminate по умолчанию никаких ресурсов не высвобождает, это же не деструктор. Она просто посылает главному потоку приложения сообщение WM_QUIT - поэтому не важно, обрабатывается ли очередь главного потока в Application или какой-то другой оконной функции, все равно обработается корректно. Т.е. если приложение и так завершает работу (если, конечно, DLL_PROCESS_DETACH не следствие FreeLibrary), лишний раз ему напоминать об этом не к чему (хотя и не повредит).
Вообще, полезно ознакомиться с первоисточником (сиречь исходниками VCL) - тогда бы эти непонятки отпали бы сами собой


 
parovoZZ ©   (2006-05-24 21:33) [19]


> Т.е. если приложение и так завершает работу (если, конечно,
>  DLL_PROCESS_DETACH не следствие FreeLibrary),

Т.е. DLL_PROCESS_DETACH тоже надо формировать ручками? А почему нельзя автоматом при FreeLibrary?


 
DrPass ©   (2006-05-25 00:26) [20]


> parovoZZ ©   (24.05.06 21:33) [19]

Да не надо ничего формировать, я совсем про другое писал. Библиотека получит свой DLL_PROCESS_DETACH, куда она денется :)


 
parovoZZ ©   (2006-05-26 00:06) [21]


> В общем, идея такая, Application.Handle в DLL, заполняется
> ручками ...

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

Что-то на строчке

MainForm := TMainForm.Create (nil);

выпадает ошибка в духе  "Could not ole window handle". А бывает не выпадает.

Короче, ну его... Форма в dll это такой гемор  брррр. Да и при выходе ругань Access Vioalatin.

Только весь проект изгадил.


 
isasa ©   (2006-05-26 00:25) [22]

Ну главную форму запихать в DLL, это круто.
Тут помочь не могу. Я такого еще не встречал. :)
Фанатизм приводит к травмам!


 
isasa ©   (2006-05-26 00:40) [23]

Немного оклемался. :)
Для VCL, это

 Application.Initialize;
 Application.CreateForm(TmainForm, mainForm);
 Application.Run;

как Библия, остальные пихай в DLL, если есть желание решать проблемы(решаеиые).


 
parovoZZ ©   (2006-05-26 01:31) [24]

А куда мне её ещё деть? У меня exe написан на АПЯХ!!!

Кароче! Убрал WebBrowser с формы - пропала ошибка с OLE.

Заккомил строчку {$R DelphiXP.res} - прекратились ошибки при завершении проги. А жаль. Всё так красиво.

А почему WebBrowser не дружит с PageControl???? Создал ту же форму в ехе - ошибка осталась. Фигня. Мне без броузера низзя.


 
isasa ©   (2006-05-26 08:05) [25]

WebBrowser - это COM(скорее всего), значит надо делать  CoInitializeEx и в EXE.
Только тип модели должен быть аналогичен, усьановленному в DLL.
Тип потоковой модели "на ходу" не меняется.


 
parovoZZ ©   (2006-05-26 09:44) [26]

Так ведь без PageControl всё работает.

А как быть с манифестом ХР? и почему он в dll не подхватывается?
Попробую в секцию 24 запихнуть.


 
GrayFace ©   (2006-05-26 12:31) [27]

По поводу [1] - Укажи ComObj в dpr где-нибудь по раньше - тогда точно должен будет проинициализироваться.

DrPass ©   (23.05.06 23:51) [11]
> > А смысл заменять у Application Handle?
>
> Ровным счетом никакого. Сообщения-то все равно будут приходить
> в оконную функцию, объявленную в основной программе, а не
> в Application.
> А в том Application, которое объявлено в DLL, вообще не
> создается ни оконная функция, ни дескриптор (это тоже фича,
>  начиная с D6)

Есть. Почти такой же как у Form.ParentWindow:=...


 
parovoZZ ©   (2006-05-26 22:20) [28]

Ладно, в задницу все эти dll с формами. Генератор глюков вышел вместо проги. Всё равно по скорости ничего не получил - dll статически грузится столько же, сколько и exe. А динамически - голова съедет.


 
Ярослав   (2006-05-27 20:50) [29]

Смотри пример  как это делаю я

Вот дллка :
library INFO;

{ Important note about DLL memory management: ShareMem must be the
 first unit in your library"s USES clause AND your project"s (select
 Project-View Source) USES clause if your DLL exports any procedures or
 functions that pass strings as parameters or function results. This
 applies to all strings passed to and from your DLL--even those that
 are nested in records and classes. ShareMem is the interface unit to
 the BORLNDMM.DLL shared memory manager, which must be deployed along
 with your DLL. To avoid using BORLNDMM.DLL, pass string information
 using PChar or ShortString parameters. }

uses
 SysUtils,
 Classes,
 Forms ,
 system,
 infomy in "infomy.pas"{imy},
 infouser in "infouser.pas"{usr},
 infouserb in "infouserb.pas"{usb},
 bvlogo in "bvlogo.pas"{logo};
 {$R *.RES}

        function infoform : integer; stdcall ;
        var
        inf: Tmyinfo ;
        begin
        inf:=tmyinfo.Create(Application);
        Result:=inf.ShowModal ;
        inf.Free ;
        end ;
        function userform: integer ;stdcall ;
        var
        infuser:Tuserinfo ;
        begin
        infuser:=Tuserinfo.Create(Application) ;
        result:=infuser.ShowModal ;
        infuser.Free ;
        end ;
        function userformb: integer ;stdcall ;
        var
        infuserb:Tuserinfob ;
        begin
        infuserb:=Tuserinfob.create(Application) ;
        result:=infuserb.showmodal ;
        infuserb.free ;
        end;
        function startbvlogo: integer ; stdcall ;
        var
        logostart:tlogo ;
        begin
        logostart:=Tlogo.create(Application);
        result:=logostart.showmodal ;
        logostart.free ;
        end ;
  exports
  infoform,
  Userform ,
  userformb,
  startbvlogo;

begin
end.

Вызов из главной формы


var
 Main_Form: TMain_Form;
  {------------------------------------}
   function infoform : integer; stdcall ;
  external "INFO.dll" ;
  function userform: integer ; stdcall ;
  external "INFO.dll" ;
  function userformb:integer; stdcall ;
  external "INFO.dll" ;
  Function startbvlogo:integer; stdcall ;
  external "info.dll"  ;
  {=====================}

procedure TMain_Form.N18Click(Sender: TObject);
begin
  startbvlogo;
end;

procedure TMain_Form.N22Click(Sender: TObject);
begin
userformb;
end;

procedure TMain_Form.N20Click(Sender: TObject);
begin
infoform;
end;

У меня все работает ..
Кроме MDI форм


 
Ярослав   (2006-05-27 21:00) [30]

Так если у вас есть дата модуль так где вы его подключаете в длл?


 
parovoZZ ©   (2006-05-27 21:31) [31]

Да не, проблема WebBrowser + PageControl в dll. Всё коннектится, грузится, но при открытии вкладки с WebBrowser вылетает ошибка типа Could not ole window handle. Всё тоже самое сделал в exe - без ошибок.



Страницы: 1 вся ветка

Форум: "Основная";
Текущий архив: 2006.07.09;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.54 MB
Время: 0.011 c
15-1150040952
Yanis
2006-06-11 19:49
2006.07.09
А ваше чадо уже программирует?


2-1150492533
FiJer
2006-06-17 01:15
2006.07.09
Помогите разобраться с компонентом


15-1150119141
[wl]
2006-06-12 17:32
2006.07.09
оффлайн-клиент IPB-форума


1-1148903038
pirate
2006-05-29 15:43
2006.07.09
Волшебный Richedit


3-1147263291
SHD
2006-05-10 16:14
2006.07.09
И снова значения по умолчанию.





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский