Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2003.07.31;
Скачать: [xml.tar.bz2];

Вниз

Допустимо ли такое обращение со строками в 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;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.51 MB
Время: 0.01 c
3-100594
Avreliy
2003-07-07 12:42
2003.07.31
Проблема с ХП


3-100581
Skywalker
2003-07-08 17:11
2003.07.31
Вставка записи в БД


1-100672
cjiohobaji
2003-07-18 05:43
2003.07.31
отчёт


3-100570
Николай
2003-07-07 15:29
2003.07.31
Работа с DbGrid...


3-100633
Black Shark
2003-07-10 12:38
2003.07.31
Динамический массив и БД





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский