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

Вниз

FreeLibrary   Найти похожие ветки 

 
ZHK ©   (2004-06-21 10:31) [0]

Здравствуйте, Господа.
Попал в затруднительную ситуацию. Тупею. :-) Вот кусок кода:


procedure TForm1.Button3Click(Sender: TObject);
var
 DialogCount:TDialogCount;
 DialogName:TDialogName;
 DialogDescription:TDialogDescription;
 DialogExecute:TDialogExecute;
 SetDatabaseList:TSetDatabaseList;
 LH:THandle;
 SQL:TStrings;
begin
//  Form6.Execute;
 LH:=LoadLibrary("dll\sql1\SQL1.dll");
 @DialogCount := GetProcAddress(LH,"DialogCount");
 @DialogName := GetProcAddress(LH,"DialogName");
 @DialogDescription := GetProcAddress(LH,"DialogDescription");
 @DialogExecute := GetProcAddress(LH,"DialogExecute");
 @SetDatabaseList := GetProcAddress(LH,"SetDatabaseList");
 if Assigned(SetDatabaseList) then
    SetDatabaseList(PostgreSQLConnectionForm.ListBox1.Items);
 SQL:=TStringList.Create;
 if Assigned(DialogExecute) then
    begin
      DialogExecute(0,SQL);
      if SQL.Count>0 then
         RichEdit1.Lines.Assign(SQL);
    end;
 SQL.Free;

 FreeLibrary(LH);  
{
А вот тут-то и возникает ошибка Invalid Floating Point Operation.
При необходимости могу прислать полный проект DLL-ки. Мое мыло - eug_elizarov@mail.ru
}

end;

Кто чем может. :-)


 
Игорь Шевченко ©   (2004-06-21 10:33) [1]

где-то stdcall забыл объявить ?


 
ZHK ©   (2004-06-21 10:51) [2]

Да я его и не объявлял. Но ведь парни пишут, что для делфи это необязательно? Или как?


 
ZHK ©   (2004-06-21 10:53) [3]

А, собственно, и не помогло. :-(


 
Игорь Шевченко ©   (2004-06-21 11:15) [4]


> Да я его и не объявлял. Но ведь парни пишут, что для делфи
> это необязательно? Или как?


Вот если бы ты привел объявления функций в DLL и в своей программе, наверное, было бы проще диагностировать ошибку...


 
ZHK ©   (2004-06-21 11:44) [5]

Вот библиотека:

library SQL1;

{ 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,
 Billing in "Billing.pas" {Form1},
 SQLTypes in "..\SQLTypes.pas";

{$R *.res}

const
 DCount=1;

var
 DialogNames:array[0..DCount-1] of String=("Âûáîðêà áèëëèíãà ïî íîìåðó àáîíåíòà"#0);
 DialogDescriptions:array[0..DCount-1] of String=("Âûáîðêà áèëëèíãà ïî íîìåðó àáîíåíòà"#0);
 DatabaseList:String;

 function DialogsCount:Integer; stdcall;
 begin
   Result:=DCount;
 end;

 function DialogName(IndexOfDialog:Integer):PChar; stdcall;
 begin
   if (IndexOfDialog>=0) and (IndexOfDialog<DCount) then
      begin
        ReallocMem(Result,Length(DialogNames[IndexOfDialog]));
        Move(DialogNames[IndexOfDialog][1],Result^,Length(DialogNames[IndexOfDialog]));
      end
   else
     Result:=Nil;
 end;

 function DialogDescription(IndexOfDialog:Integer):PChar; stdcall;
 begin
   if (IndexOfDialog>=0) and (IndexOfDialog<DCount) then
      begin
        ReallocMem(Result,Length(DialogDescriptions[IndexOfDialog]));
        Move(DialogDescriptions[IndexOfDialog][1],Result^,Length(DialogDescriptions[IndexOfDialog]));
      end
   else
     Result:=Nil;
 end;

 function DialogExecute(Index:Integer;SQL:TStrings):Boolean; stdcall;
 var
   Form:TSQLForm;
   DL:TStrings;
 begin
   case Index of
     0:Form:=TForm1.Create(Nil)
     else
       Exit;
   end;
   DL:=TStringList.Create;
   DL.Text:=DatabaseList;
   Form.SetTableNames(DL);
   DL.Free;
   Result:=Form.Execute(SQL);
   Form.Free;
 end;

 procedure SetDatabaseList(DatabaseNames:TStrings); stdcall;
 begin
   DatabaseList:=DatabaseNames.Text;
 end;

exports

 DialogsCount index 1,
 DialogName index 2,
 DialogDescription index 3,
 DialogExecute index 4,
 SetDatabaseList index 5;

begin
end.


А вот объявления типов в программе:


type

 TDialogCount=function:Integer; stdcall;
 TDialogName=function (IndexOfDialog:Integer):PChar; stdcall;
 TDialogDescription=function (IndexOfDialog:Integer):PChar; stdcall;
 TDialogExecute=function (Index:Integer;SQL:TStrings):Boolean; stdcall;
 TSetDatabaseList=procedure (DatabaseNames:TStrings); stdcall;


 
Думкин ©   (2004-06-21 11:51) [6]

А комментарий вверху для красоты?


 
Игорь Шевченко ©   (2004-06-21 11:57) [7]

ShareMem


 
ZHK ©   (2004-06-21 12:00) [8]

Не-а, ShareMem тоже не катит...


 
Думкин ©   (2004-06-21 12:04) [9]

>  [8] ZHK ©   (21.06.04 12:00)

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


 
Anatoly Podgoretsky ©   (2004-06-21 12:05) [10]

Где и как его включил,


 
ZHK ©   (2004-06-21 12:15) [11]


library SQL1;

{ 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

ShareMem,

SysUtils,
Classes,
Billing in "Billing.pas" {Form1},
SQLTypes in "..\SQLTypes.pas";



Очевидно, что сделал что-то не так. Подскажите...


 
Игорь Шевченко ©   (2004-06-21 12:24) [12]


> ShareMem must be the
> first unit in your library"s USES clause AND your project"s
> (select
> Project-View Source) USES clause


 
ZHK ©   (2004-06-21 13:11) [13]

Дык я ж его первым и поставил... А ошибка то не ушла... Да. И в модуле, где библиотека вызывается, он тоже первым стоит...


 
Игорь Шевченко ©   (2004-06-21 13:15) [14]


> И в модуле, где библиотека вызывается, он тоже первым стоит...


Надо в .dpr


 
Anatoly Podgoretsky ©   (2004-06-21 13:19) [15]

Ты приведи сначала свои USES


 
ZHK ©   (2004-06-21 13:26) [16]

В library я уже выше привел, а в модуле вот такой:

unit SQLInput;

interface

uses
 ShareMem, Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls, ExtCtrls, ComCtrls;


 
panov ©   (2004-06-21 13:29) [17]

см. Игорь Шевченко ©   (21.06.04 13:15) [14]

Нужно в файл проекта добавить первым в uses.


 
Anatoly Podgoretsky ©   (2004-06-21 13:33) [18]

ZHK ©   (21.06.04 13:26) [16]
Тебя же просилм все USES, не надо это делать по кускам.


 
ZHK ©   (2004-06-21 13:56) [19]


> Anatoly Podgoretsky ©   (21.06.04 13:33) [18]
> ZHK ©   (21.06.04 13:26) [16]
> Тебя же просилм все USES, не надо это делать по кускам.

Наверное я что-то не понял. Все uses со ВСЕХ ВХОДЯЩИХ В ПРОЕКТ МОДУЛЕЙ?


 
Игорь Шевченко ©   (2004-06-21 14:01) [20]

uses от .dpr покажи :)


 
ZHK ©   (2004-06-21 14:17) [21]


program SQLShell;

uses
 Forms,
 Windows,
 MainUnit in "MainUnit.pas" {PostgreSQLConnectionForm},
 Connection in "..\Useful\PGQuery\Connection.pas",
 ResOut in "ResOut.pas" {ResOutForm},
 SQLInput in "SQLInput.pas" {Form1},
 TextForm in "TextForm.pas" {Form2},
 DatabaseSel in "DatabaseSel.pas" {Form3},
 Logged in "Logged.pas" {Form4},
 Options in "Options.pas" {Form5},
 LoadHd in "LoadHd.pas" {LoadHead},
 SQLSelector in "SQLSelector.pas" {Form6},
 LoadPages in "LoadPages.pas";


 
Игорь Шевченко ©   (2004-06-21 14:24) [22]


>
> program SQLShell;
>
> uses
  ShareMem,>  Forms,
>  Windows,


 
ZHK ©   (2004-06-21 14:27) [23]

А сейчас уже это выглядит вот так:

program SQLShell;

uses
ShareMem,
Forms,
Windows,
MainUnit in "MainUnit.pas" {PostgreSQLConnectionForm},
Connection in "..\Useful\PGQuery\Connection.pas",
ResOut in "ResOut.pas" {ResOutForm},
SQLInput in "SQLInput.pas" {Form1},
TextForm in "TextForm.pas" {Form2},
DatabaseSel in "DatabaseSel.pas" {Form3},
Logged in "Logged.pas" {Form4},
Options in "Options.pas" {Form5},
LoadHd in "LoadHd.pas" {LoadHead},
SQLSelector in "SQLSelector.pas" {Form6},
LoadPages in "LoadPages.pas";


После всех перетрубаций первый вызов функций загруженной библиотеки успешен, повторный вызов - приводит к ошибке Access violation...

А вообще вызов преобразился следующим образом:

procedure TForm1.Button3Click(Sender: TObject);
var
 SQL:String;
begin
//  Form6.Execute;
 if LH=INVALID_HANDLE_VALUE then
    begin
      LH:=LoadLibrary("dll\sql1\SQL1.dll");
      @DialogCount := GetProcAddress(LH,"DialogCount");
      @DialogName := GetProcAddress(LH,"DialogName");
      @DialogDescription := GetProcAddress(LH,"DialogDescription");
      @DialogExecute := GetProcAddress(LH,"DialogExecute");
      @SetDatabaseList := GetProcAddress(LH,"SetDatabaseList");
      @DialogGetSQL := GetProcAddress(LH,"DialogGetSQL");
    end;
 if Assigned(SetDatabaseList) then
    SetDatabaseList(PChar(PostgreSQLConnectionForm.ListBox1.Items.Text));
 if Assigned(DialogExecute) then
    if DialogExecute(0) then
       begin
         SQL:=String(DialogGetSQL(0));
         RichEdit1.Lines.Text:=Trim(SQL);
       end;
end;

и добавился тип:

 TDialogGetSQL=function (Index:Integer):PChar;


 
Игорь Шевченко ©   (2004-06-21 14:33) [24]


>  TDialogGetSQL=function (Index:Integer):PChar;


stdcall не надо ?


 
ZHK ©   (2004-06-21 14:40) [25]

Надо, только не в этом дело. Я понял. :-) Я ж говорю - тупею.

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
var
 FH:THandle;
 I:Integer;
begin
 if CmdFileName<>"" then
    begin
      FH:=FileCreate(CmdFileName);
      for I:=0 to Length(Cmd)-1 do
        begin
          FileWrite(FH,Z[1],1);
          FileWrite(FH,Cmd[I][1],Length(Cmd[I]));
        end;
      FileClose(FH);
    end;
 if LH<>INVALID_HANDLE_VALUE then
    begin
      FreeLibrary(LH);
      LH:=INVALID_HANDLE_VALUE;
//Вот этой строчки-то и не было.
    end;
end;

То есть окно, закрываясь, выгружало библиотеку, а повторная загрузка - не производилась. Понятно, что обращаясь к несуществующей функции ошибка-то и происходила. :-) А ShareMem, насколько я понял, необходим только для правильной работы со строками. Если использовать PChar, как я это делал, то он не обязателен. Спасибо за помощь!


 
Игорь Шевченко ©   (2004-06-21 14:43) [26]


> ShareMem, насколько я понял, необходим только для правильной
> работы со строками


И с классами, которые используют строки, например TStringList


 
evvcom ©   (2004-06-22 00:07) [27]

И еще:

const
 INVALID_HANDLE_VALUE = DWORD(-1);

тогда как
LoadLibrary
If the function fails, the return value is NULL.

И изначально LH где-то нужно инициализировать в INVALID_HANDLE_VALUE. Лучше этого не делать и проверять на незагруженность библиотеки, сравнивая с 0, а не с -1.


 
ZHK ©   (2004-06-22 09:16) [28]

Спасибо, я знаю, чему равно значение INVALID_HANDLE_VALUE. А DWORD(-1) на самом деле не -1, а максимальное значение DWORD. Конечно же, это не совсем корректно, я согласен, но я не думаю что при моей жизни я когда нибудь достигну максимального значения хэндла, потому спокоен за этот код. А что до инициализации, то это делается просто:

var
 LH:THandle=INVALID_HANDLE_VALUE;

Это спасает от многого.


 
panov ©   (2004-06-22 11:12) [29]

>ZHK ©   (22.06.04 09:16) [28]

var
LH:THandle=INVALID_HANDLE_VALUE;

Это спасает от многого.


var
LH:THandle=0;

if LH=0 then LoadLibrary(...)

спасает значительно лучше...


 
evvcom ©   (2004-06-22 12:53) [30]


> на самом деле не -1, а максимальное значение DWORD

В двоичной арифметике - это одно и то же.

И все же внимательнее чти [27] и [29]



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

Форум: "WinAPI";
Текущий архив: 2004.08.01;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.53 MB
Время: 0.03 c
1-1090416204
~ShamaN~
2004-07-21 17:23
2004.08.01
Quick Report


1-1089895796
Курдль
2004-07-15 16:49
2004.08.01
Формула попадания точки в эллипс, вписанный в прямоугольник.


3-1088855543
Koala
2004-07-03 15:52
2004.08.01
Копирование данных из временной таблицы


14-1089996598
panov
2004-07-16 20:49
2004.08.01
Блин, флудеров развелось.


1-1089877399
Николай
2004-07-15 11:43
2004.08.01
Реестр





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский