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

Вниз

Допустимо ли такое обращение со строками в DLL?   Найти похожие ветки 

 
Aleksandr ©   (2003-07-15 15:52) [0]

В dll у меня есть объект-список, имеющий функцию, возвращающую свойство всех своих элементов в виде строки (string) с разделителями #13#10. В той же библиотеке есть функция, доступная для пользователей, возвращающая PChar:


function GetNamesRus : PChar; stdcall;
var
s : string;
begin
Result:=nil;
if Assigned(NamesList) then begin
s:=NamesList.GetNamesRus;
if s<>"" then
Result:=StrNew(PChar(S))
end
end;


Вроде мне казалось, что внутри DLL должно быть до фени, пользуешься string или нет, лишь бы на выход были PChar. Однако же PChar приходит какой-то кривой (мусор всякий, хотя наблюдается нечто от нужного), и при попытке ему StrDispose ругается на invalid pointer operation. Объясните мне, что тут к чему?


 
Skier ©   (2003-07-15 15:54) [1]

function title(n: Integer): PChar;

var
s: string;
begin
s := Format("title - %d", [n]);
Result := PChar(s); // DON"T DO THIS
end;

This example returns a pointer to string data that is freed when the title function returns.


 
Aleksandr ©   (2003-07-15 15:58) [2]

2 Skier:

Да? А в моем понимании между
Result:=StrNew(PChar(S))
и
Result:=PChar(S)
есть глобальная разница


 
Skier ©   (2003-07-15 15:58) [3]

Shit. Не туда ! StrNew не заметил :)
А как объявлена GetNamesRus в приложении ?


 
Юрий Федоров ©   (2003-07-15 15:58) [4]

В данном случае не наблюдается "is freed when the title function returns."
Тут дело в другом: Если память выделена в DLL, то она и освобождена должна быть в DLL.
Иначе uses ShareMem и далее по тексту комментария.
А то, что там "мусор всякий" - это странно, тут дело не в PChar или String, а в чем-то другом, например в пресловутых соглашениях о вызовах


 
Aleksandr ©   (2003-07-15 15:59) [5]

Понял. В приложении объявлено как:

function GetNamesRus : PChar; stdcall; external "disten.dll";


 
Aleksandr ©   (2003-07-15 16:01) [6]

2 Юрий Федоров :

Тяжко. Не могли бы Вы привести пример, когда из dll берется PChar и в DLL он потом освобождается? Я просто этого не представляю, в смысле организации.


 
Юрий Федоров ©   (2003-07-15 16:04) [7]

еще одну функцию в DLL - туда параметром PChar, там StrDispose


 
Skier ©   (2003-07-15 16:04) [8]

>Aleksandr © (15.07.03 16:01)
-function GetNamesRus(Buffer : PChar; BufferSize : Integer) : Integer; stdcall;
-память под Buffer выделять и освобождать в host-приложении
-Не спасёт ?




 
Aleksandr ©   (2003-07-15 16:06) [9]

%/ Надо попробовать...


 
Юрий Федоров ©   (2003-07-15 16:07) [10]

>>>Skier © (15.07.03 16:04)

Вообще с моей точки зрения этот вариант наиболее предпочтительный, я всегда так и делаю (почему-то не люблю я этот самый ShareMem), тут только один недостаток - нужно заранее знать BufferSize или выделять по максимуму


 
Skier ©   (2003-07-15 16:08) [11]

>Юрий Федоров © (15.07.03 16:04)
Не очень удачный подход, IMHO.


 
Skier ©   (2003-07-15 16:10) [12]

>Юрий Федоров © (15.07.03 16:07)


> нужно заранее знать BufferSize или выделять по максимуму


?


> почему-то не люблю я этот самый ShareMem


Дело даже не в ShareMem. Дело в том что тип String понимают только Delphi и Builder и вот здесь может крыться угроза. :)


 
Юрий Федоров ©   (2003-07-15 16:11) [13]

>>Skier © (15.07.03 16:08)
Вопрос философский...
Тем не менее многие функции API организованы именно так


 
clickmaker ©   (2003-07-15 16:11) [14]

procedure GetNamesRus(var Buffer : PChar);
begin
if Assigned(NamesList) then begin
s:=NamesList.GetNamesRus;
Buffer := PChar(LocalAlloc(Length(s)+1));
StrPCopy(Buffer, s);
end;
end;

В host"e LocalFree


 
Юрий Федоров ©   (2003-07-15 16:12) [15]

>>Skier © (15.07.03 16:10)
>>понимают только Delphi и Builder
На практике этого чаще всего достаточно :-)


 
Skier ©   (2003-07-15 16:13) [16]

>Юрий Федоров © (15.07.03 16:11)
Дык,...поэтому я и написал "IMHO" :)


 
Aleksandr ©   (2003-07-15 16:14) [17]

Мда, я вот над этим сейчас глубоко и задумался... То есть в функцию уже загоняется буфер с выделенным размером BufferSize, а возвращается, сколько надо? То есть программист должен выделить (кстати, сколько лучше?), получить неверный результат, освободить и выделить еще раз с возвращенным значением?


 
Aleksandr ©   (2003-07-15 16:16) [18]

2 clickmaker :
О, Ваше сообщение не заметил сразу... Глупый вопрос: а почему процедурой, а не результатом?


 
Юрий Федоров ©   (2003-07-15 16:16) [19]

Что думает общественность по поводу предложенного clickmaker ©
варианта LocalAlloc? Я что-то в сомнениях...


 
clickmaker ©   (2003-07-15 16:19) [20]

Aleksandr © (15.07.03 16:16)
2 clickmaker :
О, Ваше сообщение не заметил сразу... Глупый вопрос: а почему процедурой, а не результатом?


Непринципиально. Главное, что память, захваченную LocalAlloc в DLL, можно освободить в EXE.

Юрий Федоров © (15.07.03 16:16)
Что думает общественность по поводу предложенного clickmaker ©
варианта LocalAlloc? Я что-то в сомнениях...


А зря. Это работающий пример.


 
Skier ©   (2003-07-15 16:19) [21]

>Aleksandr
http://www.compress.ru/Temp/990/index.htm#03


 
Толик ©   (2003-07-15 16:21) [22]

imho, хорошим тоном является правило "кто выделяет память, тот её и освобождает" (см. большинство ф-й WinAPI). Так и для понимания проще да и для отладки.


 
Aleksandr ©   (2003-07-15 16:32) [23]

Спасибо всем... будем делать :)


 
Aleksandr ©   (2003-07-15 17:29) [24]

О-о... не так все просто с этими локалами... Для LocalAlloc влаги какие-то надо указать, и возвращает она Хэндл памяти, а LocalFree(P) не прокатывает - дай, говорит, переменную типа кардинал. :(
Кстати, а вообще, можно ли создавать в dll классы, которые понимались бы другими программами? У меня эта строка - это переформатированные объекты с пропертями через запяточия, и разбирать ее потом на объекты обратно - тоже не подарок. Но что-то нигде я описаний не встречал такой работы, чтобы функцией получить из dll список объектов описанного в dll же типа.


 
Юрий Федоров ©   (2003-07-15 17:30) [25]

>>Aleksandr © (15.07.03 17:29)
Может быть интерфейсы спасут отца русской демократии ?


 
Fantasist.   (2003-07-16 02:52) [26]


> Кстати, а вообще, можно ли создавать в dll классы, которые
> понимались бы другими программами?


Можно - ActiveX называется.


 
Aleksandr ©   (2003-07-16 17:13) [27]

Скажите, а при варианте:
function GetNamesRus(Buffer : PChar; BufferSize : Integer) : Integer; stdcall;

чем память на хосте под буфер выделять, никаких ограничений нет? Например, можно ли использовать GetMem:

var
pNames : PChar;
Size : integer;
begin
Size:=GetNamesRus(nil,0); //при неназначенном буфере она просто возвращает необходимый размер
GetMem(pNames,Size);
try
if GetNamesRus(pNames,Size)=Size then ...
finally
FreeMem(pNames)
end
end


 
Юрий Федоров ©   (2003-07-16 17:15) [28]

Можно. Не забудь про память под завершающий 0 :-)


 
clickmaker ©   (2003-07-16 17:35) [29]

Aleksandr © (15.07.03 17:29)
О-о... не так все просто с этими локалами... Для LocalAlloc влаги какие-то надо указать


LocalAlloc(Size, LPTR), откастить к нужному указателю


 
Aleksandr ©   (2003-07-16 18:16) [30]

Спасибо истчо раз. Постараюсь не забыть :)


 
Fredericco ©   (2003-07-16 19:39) [31]


implementation
var
hGlobalMemory: THandle;
.......
function ReturnString(StringIn: Pchar): Pchar ;
var
lpGlobalMemory: pointer ;
begin
lpGlobalMemory:=nil;
hGlobalMemory := Global ReAlloc(hGlobalMemory,strlen(StringIn)+1, GMEM_MOVEABLE);
if hGlobalMemory <> 0 then
begin
lpGlobalMemory := GlobalLock(hGlobalMemory);
lstrcpy(lpGlobalMemory,StringIn);
GlobalUnlock(hGlobalMemory);
end;
ReturnString := Pchar(lpGlobalMemory);
end;
.....
function GetHBusyMem:THandle;
begin
Result:=hGlobalMemory;
end;
.............
initialization
......
hGlobalMemory := GlobalAlloc(GMEM_MOVEABLE , 1);


Меня спасает при передаче строк любой длины.
Только не забудь в хост программе объявить функ. GetHBusyMem (вызывать не обязательно). Понимаю, что глупость, но без нее у меня память кушается...


 
Fredericco ©   (2003-07-16 19:41) [32]

Совсем забыл!!!



function GetNamesRus : PChar; stdcall;
begin
.....
Result:=ReturnString(PChar(%YourString%));
end;



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

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

Наверх




Память: 0.55 MB
Время: 0.018 c
3-100530
Skalp
2003-07-07 14:42
2003.07.31
Блокировка


1-100751
TCrash
2003-07-16 12:31
2003.07.31
ASM и время


9-100524
Axis_of_Evil
2003-02-05 10:02
2003.07.31
А где взять картинки а-ля Диабло, Варкрафт?


8-100829
Ильдар
2003-04-05 13:04
2003.07.31
Слушаем радио


11-100659
romychk
2002-11-28 13:02
2003.07.31
Размер программы