Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2002.04.18;
Скачать: CL | DM;

Вниз

Передать из DLL большую строку   Найти похожие ветки 

 
MaxSit ©   (2002-04-04 20:45) [0]

Вопрос такой: как из DLL передать очень длинную строку? Использовать String и Sharemem к ниму не предлогать.
Заранее спасибо.


 
LazorenkoX ©   (2002-04-04 20:51) [1]

PChar


 
MaxSit ©   (2002-04-04 21:03) [2]

Да вот, не пашет. Говорит, Аксес виолатион у Вас, батенька.

procedure MyProc(var Per: PChar); StdCall; external DLL_Const Name "MyProcDLL";

q:=LoadLibrary(DLL_Const);
Per:=PChar("Привет");
MyProc(Per);
showmessage(Per); --> вот и вылетает;
FreeLibrary(q);

Что я делаю не так?


 
MaxSit ©   (2002-04-04 21:03) [3]

Да вот, не пашет. Говорит, Аксес виолатион у Вас, батенька.

procedure MyProc(var Per: PChar): Boolean; StdCall; external DLL_Const Name "MyProcDLL";

q:=LoadLibrary(DLL_Const);
Per:=PChar("Привет");
MyProc(Per);
showmessage(Per); --> вот и вылетает;
FreeLibrary(q);

Что я делаю не так?


 
LazorenkoX ©   (2002-04-04 21:23) [4]

Твой Unit:

//Сначала надо объявить процедуру
function MyProc(var Per: PChar): Boolean;

implantation

begin
//Загружаем библиотеку
q:=LoadLibrary(DLL_Const);
//ЗАДАЁМ АДРЕС ПРОЦЕДУРЫ!!! (точно не помню параметры):
@MyProc:=GetProcAddress(q, "MyProc");
//Теперь вызываем.
MyProc(Per);
showmessage(Per); --> вот и вылетает;
FreeLibrary(q);
end;

Если не получится попробуем изменить код ДЛЛки


 
Fantasist   (2002-04-04 22:43) [5]

Да нет, подключать можно и статически, тогда LoadLibrary делать не надо.
Покажи код MyProc.


 
MaxSit ©   (2002-04-04 23:13) [6]

Ошибка возникает, если вызываешь и статически и динамически, разницы нет.

Вот сама DLL:

procedure MProcDLL(Per: PChar); StdCall; exports MProcDLL;
...
procedure MProcDLL(Per: PChar);
begin
try
Application.Create(TForm1, Form1);
Form1.Memo1.Add(Per);
Form1.ShowModal;
Per:=PChar(Form1.Memo1.Text); // может тут загвостка, предполагаю.
finally
Form1.Hide;
Form1.Free;
end;
end;

Мне кажется, что PCHAR это указатель, который теряется после уничтожения формы. Поправьте, если не так.


 
Fantasist   (2002-04-05 00:01) [7]

>Ошибка возникает, если вызываешь и статически и динамически, разницы нет.

Mы в это и не сомневались. Тут лучше действительно потрейсить dll так как скорее всего твое предположение верно. PChar - это указатель на char, а преобразование:

p:pchar;
s:string;
p:=PChar(s);

скорее всего означает то же, что и
p:=@s[1];

Да должно быть так. Я просто точно не помню, может все-таки Delphi извратился, и создает копию, но это легко проверить.


 
MaxSit ©   (2002-04-05 00:22) [8]

Причем, если сделать:

try
// Application.Create(TForm1, Form1);
// Form1.Memo1.Add(Per);
// Form1.ShowModal;
Per:=PChar("Блин, ну когда уже заработает");
finally
// Form1.Hide;
// Form1.Free;
end;
end;

то все работает без проблем ??? Значит побороть то можно...


 
LazorenkoX ©   (2002-04-05 00:28) [9]

Это конечно глупое предположение, но давай сделаем как можно меньше сомнений.

Попробуй добавь это в главный бегин ДЛЛки:

begin
Application.Initialize;
Form1 := TForm1.Create(Application);
Application.Run;
end;


И убери из своего кода Application.Create(TForm1, Form1);


 
MaxSit ©   (2002-04-05 00:45) [10]

Идея интересная, даже все заработало, но стала выдаваться следующая ошибка, после завершения всего приложения:

"A call to an OS function failed."

Заработал другой вариант: объявил глобальную переменную в DLL, присваеваю значение Form1.Memo1.Text, затем грохаю форму, и только потом пишу:

Per:=PChar(Global_Var_PChar);

Все работает, спасибо за наводку.


 
MaxSit ©   (2002-04-05 00:48) [11]

Вероятно не очень понятно:

Вот сама DLL:

procedure MProcDLL(Per: PChar); StdCall; exports MProcDLL;

var Global_Var_PChar: String;
...
procedure MProcDLL(Per: PChar);
begin
try
Application.Create(TForm1, Form1);
Form1.Memo1.Add(Per);
Form1.ShowModal;
Global_Var_PChar:=Form1.Memo1.Text;
finally
Form1.Hide;
Form1.Free;
end;
Per:=PChar(Global_Var_PChar);
end;
и именно в таком порядке...


 
Sergey_n ©   (2002-04-05 01:15) [12]

Попробй поюзать SAFEARRAY, иногда помогает ;))))


 
Fantasist   (2002-04-05 02:43) [13]

Ну че вы извращаетесь то. :) Клуб мазохистов? :D

Почему работает это:
Per:=PChar("Блин, ну когда уже заработает");

Потому что, в отличие от:
Per:=PChar(Form1.Memo1.Text);

Здесь не только возвращается адрес(его пока еще не существует), но и выделяется память. То есть вначале она выделяется, а потом возвращается адрес на эту память.Функции WinApi в таких случаях требуют от вас выделить память, прежде чем передавать им PChar.
Можно так и делать в вашем случае. Память можно выделить StrAlloc. Это можно, конечно, сделать и в dll, но тогда клиент должен сам заботиться об освобождении памяти.

Так как у вас здесь:

var Global_Var_PChar: String;
...
procedure MProcDLL(Per: PChar);
begin
try
Application.Create(TForm1, Form1);
Form1.Memo1.Add(Per);
Form1.ShowModal;
Global_Var_PChar:=Form1.Memo1.Text;
finally
Form1.Hide;
Form1.Free;
end;
Per:=PChar(Global_Var_PChar);
end;


Выглядит очень удобно, так как компилятор за вас производит необходимое выделение и освобождение памяти(операции с переменно string) Однако, вот так вот:
Per:=PChar(Global_Var_PChar);
Вы передаете адрес на ваш Glodal string и клиент использует этот адрес. Теперь если вы внезапно поменяете значение Global_Var_PChar в своей dll, то клиент с удивлением обнаружит, что его строка которую он получил из вашей dll изменилась сама собой без всяких действий с его стороны!



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

Текущий архив: 2002.04.18;
Скачать: CL | DM;

Наверх




Память: 0.5 MB
Время: 0.01 c
1-57760
Oleon
2002-04-05 16:23
2002.04.18
Ворос с печатью бланков строгой отчетности.


4-57919
Dimaond Cat
2002-02-15 15:50
2002.04.18
Перерисовка компонентов в риалтайм


1-57732
LazorenkoX
2002-04-04 21:58
2002.04.18
Консоль вопрос 1


14-57862
Swinger
2002-03-06 23:24
2002.04.18
Игры


6-57828
Брыкун Дмитрий
2002-02-06 17:22
2002.04.18
Отправка почты.