![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
DLL, весь день бошкой о стену бюсь... [D7, WinXP]
x.pro © (2005-12-15 00:43:00)Здравствуйте!
С библиотеками еще не сталкивался, практически ничего о них не знаю. Перечитал множество разных статей, какими обладал, но, увы, ответа не нашел. :(
Короче, задача такая. Есть главная форма (MainForm), есть библиотека (например, MyDLL), есть форма, пришитая к этой библиотеке (DllForm). Мне нужно, что бы брались данные из DllForm и передавались в MyDLL. а уже из MyDLL в MainForm.
Я пробовал таким образом, но без результатно. Где кроется ошибка?
library MyDLL;
uses
SysUtils,Classes,Forms,Controls,
formx in 'formx.pas' {DLLForm}
function RetResProg(): PChar; stdcall
var s: string;
begin
DLLForm := TDLLForm.Create(Application);
DLLForm.ShowModal;
if DLLForm.ShowModal = mrOk then
begin
if DLLForm.Edit1.Text > '' then s := s + (DLLForm.Edit1.Text);
if DLLForm.Edit2.Text > '' then s := s + (DLLForm.Edit2.Text);
if DLLForm.Edit3.Text > '' then s := s + (DLLForm.Edit3.Text);
end;
result := pchar(s);
DLLForm.Free;
end;
exports RetResProg;
{$R *.res}
begin
end.
дайте пожалуйста ссылку и приведите пример кода.
Спасибо!
DesWind (2005-12-15 17:43:00) [1]
> x.pro (15.12.05 17:06) [16]
У меня работает. ищи ошибку в другом месте. Отладчиком. А через файл обмениваться между приложением и библиотекой эт коряво как-то в твоем случае.
x.pro (2005-12-15 17:42:00) [2]Спасибо всем!
Morgoth_ (2005-12-15 17:28:00) [3]для примера вот, сам где-то брал, под себя переделал немного:
GData - тип Record.
procedure OpenGlobalData;
begin
// Пытаемся открыть объект файлового отображения в память (возможно он уже был создан)
hMMF := OpenFileMapping(FILE_MAP_ALL_ACCESS, true, MMFName);
if hMMF = 0 then // если объект ещё не был создан
begin
{ Создаём объект файлового отображения в память, значение INVALID_HANDLE_VALUE = -1 и говорит о том,
что данные будут отображены в файл "подкачки" }
hMMF := CreateFileMapping(INVALID_HANDLE_VALUE, nil, PAGE_READWRITE, 0, SizeOf(TGlobalData), MMFName);
if hMMF = 0 then
begin
MessageBox(0, 'Не удалось создать объект файлового отображения в память !!',
'Error (OpenGlobalData -> CreateFileMapping)', MB_OK + MB_ICONERROR);
DLLProc := nil;
HALT
end
end;
{ Отображаем глобальные данные на АП вызывающего процесса и
получаем указатель на начало выделенного пространства }
GData:= MapViewOfFile(hMMF, FILE_MAP_ALL_ACCESS, 0, 0, SizeOf(TGlobalData));
if GData = nil then
begin
MessageBox(0, 'Не удалось отобразить глобальные данные на АП вызывающего процесса !!',
'Error (OpenGlobalData -> MapViewOfFile', MB_OK + MB_ICONERROR);
CloseHandle(hMMF);
DLLProc := nil;
HALT
end
end;
{--- Закрытие глобальных данных ---}
procedure CloseGlobalData;
begin
if GData <> nil then
begin
UnmapViewOfFile(GData);
GData := nil
end;
if hMMF <> 0 then
begin
CloseHandle(hMMF);
hMMF := 0
end
end;
Morgoth_ (2005-12-15 17:25:00) [4]данные из формы в файл. а при окончании работы библиотеки считывать из этого файла нужные данные
Существует, общую память используй, и храни там глобальные переменные.
x.pro (2005-12-15 17:06:00) [5]> DesWind © (15.12.05 16:59) [15]
Так, уже хорошо. AV не возникает. Только в диалоге основной программы все равно пусто.
У меня идея появилась, но ей я не особо хочу пользоваться, но наверное придется. Идея состоит вот в чем: записывать данные из формы в файл. а при окончании работы библиотеки считывать из этого файла нужные данные. Но может, все же, есть иной способ?
DesWind (2005-12-15 16:59:00) [6]
> x.pro (15.12.05 16:47) [14]
Если в библиотеке деректива stdcall, то и в остновной программе ее тоже надо посавить, паскалевский вызов отличается от стандартного.
x.pro (2005-12-15 16:47:00) [7]Так оно и есть! У меня ж ведь ShareMem стоит на первом месте.
umbra (2005-12-15 16:42:00) [8]ShareMem должен быть первым в uses модуля myproject.dpr
x.pro (2005-12-15 16:30:00) [9]> DesWind © (15.12.05 11:39) [11]
Вы это имели ввиду?
library MyDLL;
uses ShareMem, SysUtils, Classes,Forms,Controls,
formx in 'formx.pas' {Form1};
function RetResProg(): String; stdcall
var s: string;
begin
DllForm := TDllForm.Create(Application);
DllForm.ShowModal;
if DllForm.ShowModal = mrOk then
result := DllForm.Edit1.Text+ DllForm.Edit2.Text+ DllForm.Edit3.Text;
DllForm.Free;
end;
exports RetResProg;
{$R *.res}
begin
end.
И кусок основной программы:
...
uses ShareMem,...
...
procedure TMainForm.Button1Click(Sender: TObject);
var
RetResProg: function: string;
begin
@RetResProg := nil;
LibHandle := LoadLibrary('MyDll.dll');
if LibHandle <> 0 then
begin
@RetResProg := GetProcAddress(LibHandle,'RetResProg');
if @RetResProg <> nil then
ShowMessage( RetResProg() );
end else begin ShowMessage('Loading DLL failed...'); end;
FreeLibrary(LibHandle);
end;
тогда av в ответ. Есть у кого нибудь толковая статья по написанию DLL? Или, может, реализация моей идеи должна осуществляться с помощью файлов?
DesWind (2005-12-15 11:39:00) [10]А кто под результат память будет выделять? Лучше уж добаить модуль ShareMem и пользовать тип string
umbra (2005-12-15 11:38:00) [11]2 wal © (15.12.05 11:36) [9]
да, точно. сам наконец-то до конца дочитал :)
wal (2005-12-15 11:36:00) [12]Незнаю, что у тебя за глюки, но первое, что бросается в глаза, это
result := pchar(s);
где s - локальная переменная, которая, мягко говоря, перестает существовать при выходе из функции.
> а Вы читали примечание в начале модуля MyDLL?
Если вы про ShareMem, то оно тут ни к чему.
umbra (2005-12-15 11:30:00) [13]а Вы читали примечание в начале модуля MyDLL?
x.pro (2005-12-15 01:17:00) [14]А если записать так:
if DLLForm.ShowModal = mrOk then
result := PCHar(DLLForm.Edit1.Text+ DLLForm.Edit2.Text+ DLLForm.Edit3.Text);
то выводит в сообщении всякую абракадабру.
x.pro (2005-12-15 01:13:00) [15]Тю, Боже мой, простите, совсем вас запутал... Видимо перенапряжение сказывается. ~8-|
При выполнении программы. показывает пустой диалог, без всяких надписей.
x.pro (2005-12-15 01:10:00) [16]LibHandle: THandle; - глобальная переменная.
x.pro (2005-12-15 01:09:00) [17]Ага. Как при выполнении программы, показывает сообщение: "Loading DLL failed...". что я не так делаю?
x.pro (2005-12-15 01:07:00) [18]Ну не знаю. Если хотите, я приведу код и из MainForm. Может там чего не так....
вот он:
procedure TForm1.Button1Click(Sender: TObject);
var
RetResProg: function: Pchar;
begin
@RetResProg := nil;
LibHandle := LoadLibrary('MyDLL.dll');
if LibHandle <> 0 then
begin
@RetResProg := GetProcAddress(LibHandle,'RetResProg');
if @RetResProg <> nil then ShowMessage( StrPas(RetResProg()) );
end
else begin ShowMessage('Loading DLL failed...') end;
FreeLibrary(LibHandle);
end;
а за какие мелкие баги вы говорили?
DrPass (2005-12-15 00:57:00) [19]И что не работает?
Сама по себе DLL написана правильно, если не считать мелких багов вроде работы с переменной s.
x.pro (2005-12-15 00:46:00) [20]дайте пожалуйста ссылку илиприведите пример кода.
А то уж многовато хочу.... ;)