Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Передача и получение строк из DLL [D7, 2000, XP]


dreamse ©   (2006-11-23 19:54:00) 

Приветсвую. Подскажите как нормально передавать строки в DLL и обратно

Подключение ShapeMem исключаеться так как неудобно

Через Pchar не получаеться, выдаёт какие то крякозябли :(
ShortString анологично - крякозабли ...

Подсказали передавать массив + размер массива а потом его востанавливать , но немогу разобраться как так как с массивами не работал нормально :(


Leonid Troyanovsky   (2006-11-25 12:14:00) [1]


> dreamse   (23.11.06 23:31) [8]
> > Desdechado ©   (23.11.06 22:44) [6]

> В этом то и была вся пробламма !! Спасибо !


Это вовсе не вся проблема.
Читать [3] до просветления.

--
Regards, LVT.


dreamse   (2006-11-23 23:31:00) [2]

> Desdechado ©   (23.11.06 22:44) [6]

В этом то и была вся пробламма !! Спасибо !

Всем большое спасибо ! :)


Loginov Dmitry   (2006-11-23 23:25:00) [3]

> Подключение ShapeMem исключаеться так как неудобно


Это что еще за монстр?


Desdechado   (2006-11-23 22:44:00) [4]

и помни - соглашения о вызовах должны быть одинаковы для функции. Если она у тебя в DLL описана как stdcall, то и в вызывающей программе тоже должна


dreamse   (2006-11-23 22:32:00) [5]

Буду возиться с памятью :)


dreamse   (2006-11-23 22:23:00) [6]

Спасибо конечно , буду разбираться. Но все кстати говорят что Pchar нормально передаёться ...

Когда передаю строку из DLL отлично принимаеться строка и всё ништяк.
Когде же передаю Строку в DLL то она приходит уже искажёная ... :(


EXE

procedure texts(value:pchar); external 'Project1.dll';

procedure TForm1.Button1Click(Sender: TObject);
begin
texts(Pchar('123'));
end;

DLL

procedure texts(value:pchar); stdcall;
begin
Showmessage(StrPas(value));
end;

exports
texts;



Блин ... неужели нельзя просто передать строку блин в DLL ?


Джо   (2006-11-23 21:36:00) [7]

А посмотри, каковы способы передачи того-же PChar'а в функциях WinAPI. Суть в том, что PChar — это всего-лишь указатель на некую область памяти, в которой, предположительно, будет находиться нечто вроде "строки", т.е., печатаемые символы с завершающим символом с кодом 0.

Теперь смотри, что у тебя получается.
1. В функции ApiGetPath ты заводишь (неявно) константу-строку ('C:\1111...');
2. Приводишь ее к типу PChar.
3. Строки в Делфи — это объекты с управляемым временем жизни. Как только счетчик использования строки становится равным 0 (например, после выхода из функции, как у тебя), то этот объект разрушается.
4. Однако, адрес на эту область памяти ты возвращаешь в качестве результата функции. Повторяю, адрес, по которому строки уже нет.

Как поступать? Есть разные подходы, они отражены в WinAPI.
1. Выделяем память (динамически) под строку в самой функции. Возвращаем адрес на нее. Вызывающая программа, после того, как эта "строка" перестанет быть ей нужной, очищает память.

function ApiGetPath: Pchar; stdcall;
const
 S = 'c:\123\456';
begin
 GetMem (Result, Length(S));
 StrCopy(Result,S)
end;

procedure TForm1.Button1Click(Sender: TObject);
var
 P: PChar;
begin
 P := ApiGetPath;
 ShowMessage (P);
 FreeMem(P);
end;

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

2. Выделять память в основной программе и передавать указатель (PChar) на него в функцию, чтобы она записывала по этому адресу данные. Тонкость тут в чем? В том, что нужно заранее знать, сколько памяти выделить. Поступают обычно так: делают еще одну функцию, возвращающую размер, необходимый для хранения данных. В WinAPI это пара функций GetWindowTextLength/GetWindowText, используемых совместно. Второй подход: при передаче функции в кач-ве параметра nil она должна возвратить объем памяти, который ей необходим. После этого делается уже второй вызов, с указанием размера В WinAPI таких функций тоже немало.

function ApiGetPath2 (P: PChar): Integer;
const
 S = 'c:\123\456';
begin
 if P = nil then
   Result := Length(S)
 else
 begin
   StrCopy (P,S);
   Result := 0;
 end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
 P: PChar;
 N: Integer;
begin

 N := ApiGetPath2(nil);
 GetMem (P, N);
 try
   ApiGetPath2(P);
   ShowMessage (P);
 finally
   FreeMem (P);
 end;
end;


Преимущества — память выделяется и освобождается в одном месте. Недостатки — некоторая громоздкость.

Остальные способы — комбинации и вариации этих основных.
В таком аксепте, в общем, почитай хорошие книги :)

---
Писал это все в спешке, поэтому неисключены опечатки, ляпы, описки и просто грубые ошибки ;)


dreamse   (2006-11-23 20:14:00) [8]

> Джо ©   (23.11.06 19:56) [1]

Возможно :)

В чём ошщибка ?

EXE :



Function ApiGetPath:pchar; external 'my.dll';

procedure TForm1.Button1Click(Sender: TObject);
begin
Showmessage(ApiGetPath);
end;



DLL



function ApiGetPath: Pchar; stdcall;
begin
   result := Pchar('C:\1111\222\333');
end;



В ответ приходит либо крякозябли либо буква С :)


Джо   (2006-11-23 19:56:00) [9]

> Через Pchar не получаеться, выдаёт какие то крякозябли :
> (
> ShortString анологично - крякозабли ...

Есть предложение — научиться передавать правильно, без кракозябликов.


Наверх

Титульная страница Поиск, карта сайта Написать письмо