![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
FreeLibrary [D5, D6, D7, Win2k, WinXP]
ZHK © (2004-06-21 10:31:00)Здравствуйте, Господа.
Попал в затруднительную ситуацию. Тупею. :-) Вот кусок кода:
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;
Кто чем может. :-)
evvcom (2004-06-22 12:53:00) [1]
> на самом деле не -1, а максимальное значение DWORD
В двоичной арифметике - это одно и то же.
И все же внимательнее чти [27] и [29]
panov (2004-06-22 11:12:00) [2]>ZHK © (22.06.04 09:16) [28]
var
LH:THandle=INVALID_HANDLE_VALUE;
Это спасает от многого.
var
LH:THandle=0;
if LH=0 then LoadLibrary(...)
спасает значительно лучше...
ZHK (2004-06-22 09:16:00) [3]Спасибо, я знаю, чему равно значение INVALID_HANDLE_VALUE. А DWORD(-1) на самом деле не -1, а максимальное значение DWORD. Конечно же, это не совсем корректно, я согласен, но я не думаю что при моей жизни я когда нибудь достигну максимального значения хэндла, потому спокоен за этот код. А что до инициализации, то это делается просто:
var
LH:THandle=INVALID_HANDLE_VALUE;
Это спасает от многого.
evvcom (2004-06-22 00:07:00) [4]И еще:
const
INVALID_HANDLE_VALUE = DWORD(-1);
тогда как
LoadLibrary
If the function fails, the return value is NULL.
И изначально LH где-то нужно инициализировать в INVALID_HANDLE_VALUE. Лучше этого не делать и проверять на незагруженность библиотеки, сравнивая с 0, а не с -1.
Игорь Шевченко (2004-06-21 14:43:00) [5]
> ShareMem, насколько я понял, необходим только для правильной
> работы со строками
И с классами, которые используют строки, например TStringList
ZHK (2004-06-21 14:40:00) [6]Надо, только не в этом дело. Я понял. :-) Я ж говорю - тупею.
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:33:00) [7]
> TDialogGetSQL=function (Index:Integer):PChar;
stdcall не надо ?
ZHK (2004-06-21 14:27:00) [8]А сейчас уже это выглядит вот так:
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:24:00) [9]
>
> program SQLShell;
>
> uses
ShareMem,> Forms,
> Windows,
ZHK (2004-06-21 14:17:00) [10]
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:01:00) [11]uses от .dpr покажи :)
ZHK (2004-06-21 13:56:00) [12]
> Anatoly Podgoretsky © (21.06.04 13:33) [18]
> ZHK © (21.06.04 13:26) [16]
> Тебя же просилм все USES, не надо это делать по кускам.
Наверное я что-то не понял. Все usesсо ВСЕХ ВХОДЯЩИХ В ПРОЕКТ МОДУЛЕЙ?
Anatoly Podgoretsky (2004-06-21 13:33:00) [13]ZHK © (21.06.04 13:26) [16]
Тебя же просилм все USES, не надо это делать по кускам.
panov (2004-06-21 13:29:00) [14]см. Игорь Шевченко © (21.06.04 13:15) [14]
Нужно в файл проекта добавить первым в uses.
ZHK (2004-06-21 13:26:00) [15]В library я уже выше привел, а в модуле вот такой:
unit SQLInput;
interface
uses
ShareMem, Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, ComCtrls;
Anatoly Podgoretsky (2004-06-21 13:19:00) [16]Ты приведи сначала свои USES
Игорь Шевченко (2004-06-21 13:15:00) [17]
> И в модуле, где библиотека вызывается, он тоже первым стоит...
Надо в .dpr
ZHK (2004-06-21 13:11:00) [18]Дык я ж его первым и поставил... А ошибка то не ушла... Да. И в модуле, где библиотека вызывается, он тоже первым стоит...
Игорь Шевченко (2004-06-21 12:24:00) [19]
> ShareMem must be the
> first unit in your library's USES clause ANDyour project's
> (select
> Project-View Source) USES clause
ZHK (2004-06-21 12:15:00) [20]
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';
Очевидно, что сделал что-то не так. Подскажите...