![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Передача строк в/из функции dll
Aldor_ © (2004-08-06 15:41:00)В функцию из одной из стандартных библиотек windows в качестве выходного параметра должна передаваться структура, содержащая указатели на строки.
В описании параметра написано слелующее:
Strings returned by InternetQueryOption are globally allocated, so the calling application must free them when it is finished using them.
Это что же получается, ОН(она) память выделяет, а Я должен ее освобождать?!
Что означает globally allocated?
Под саму структуру (в том числе и указатели на строки) память выделять и освобождать мне?
И что передавать в качестве размера буфера?
VMcL (2004-08-08 16:56:00) [1]>> Aldor. (08.08.04 15:09) [14]
> Почему это является признаком того, что память не считается занятой "глобально"?
Потому что ты сам её выделил GetMem'ом.
Aldor. (2004-08-08 15:09:00) [2]VMcL © (08.08.04 12:11) [13]
> ProxyInfo^.lpszProxy указывает как раз на область памяти сразу за структурой INTERNET_PROXY_INFO
Почему это является признаком того, что память не считается занятой "глобально"?
> Только, чтобы не "угадывать" MaxStrSize, следует писать так:
Угу, так точно, то был черновой вариант.
VMcL (2004-08-08 12:11:00) [3]>> Aldor_ (07.08.04 15:11) [12]
> Таким образом избавляемся от "локальных" накладок, но, возможно, "глобально" эта память все еще считается занятой.
Не считается. Если посмотришь в Watch, то ProxyInfo^.lpszProxy указывает как раз на область памяти сразу за структурой INTERNET_PROXY_INFO, которую ты предусмотрительно резеревируешь с помощью MaxStrSize. Только, чтобы не "угадывать" MaxStrSize, следует писать так:
procedure TForm1.Button1Click(Sender: TObject);
var
StructSize: DWORD;
ProxyInfo: PInternetProxyInfo;
begin
StructSize := 0;
if not InternetQueryOption(nil, INTERNET_OPTION_PROXY, nil, StructSize) then
if GetLastError <> ERROR_INSUFFICIENT_BUFFER then RaiseLastOSError;
GetMem(ProxyInfo, StructSize);
try
if not InternetQueryOption(nil, INTERNET_OPTION_PROXY, ProxyInfo, StructSize) then
RaiseLastOSError;
ShowMessage(ProxyInfo^.lpszProxy);
finally
FreeMem(ProxyInfo);
end;
end;
Aldor_ (2004-08-07 15:11:00) [4]Провел маленькое исследование.
Если вызывать функцию в таком виде:
InternetQueryOption(nil, INTERNET_OPTION_PROXY, ProxyInfo, StructSize);Строка (ProxyInfo^.lpszProxy) пишется по адресу ProxyInfo + SizeOf(TInternetProxyInfo), т.е. внагляк сразу после структуры по стеку.
Освободить память при помощи GlobalFree(HGLOBAL(ProxyInfo^.lpszProxy)) не получилось, как и следовало ожидать, это некорретное преобразование.
Работающим (но не факт что корректным) вариантом оказался такой:
StructSize := SizeOf(TInternetProxyInfo) + MaxStrSize;
GetMem(ProxyInfo, StructSize);
try
if not InternetQueryOption(nil, INTERNET_OPTION_PROXY, ProxyInfo, StructSize) then
RaiseLastOSError;
ShowMessage(ProxyInfo^.lpszProxy);
finally
FreeMem(ProxyInfo);
end;
Таким образом избавляемся от "локальных" накладок, но, возможно, "глобально" эта память все еще считается занятой.
Буду благодарен, если кто подскажет корректный вариант глобального освобождения памяти.
Aldor_ (2004-08-06 16:43:00) [5]Спасибо за помощь!
VMcL (2004-08-06 16:35:00) [6]>> Aldor_ (06.08.04 16:26) [9]
> Правильно?
А Гейтс его знает. Почитай в справке. Там примеры есть. А вообще, как любит говорить Игорь Шевченко, "практика - критерий истины".
Aldor_ (2004-08-06 16:26:00) [7]VMcL © (06.08.04 16:19) [7]
Пока один отвечает, другой уже запостить успевает :)
[6]:
Да, читал но не разобрался, понял вот так:
Память под структурувыделяю и освобождаю сам (GetMem/FreeMem)
Память под строкивыделяет функция, но освобождаю я сам с помощьюGlobalFree(HGLOBAL(PointerToString))
Правильно?
VMcL (2004-08-06 16:19:00) [8]>> Aldor_ (06.08.04 16:15) [5]
Приведение типов отменили?
Aldor_ (2004-08-06 16:19:00) [9]VMcL © (06.08.04 16:12) [4]
InternetQueryOption( NULL,INTERNET_OPTION_USER_AGENT,NULL,&dwSize);
Функция с ЭТИМ параметром возвращает всего лишь строку, а с INTERNET_OPTION_PROXY возвразает структуру TInternetProxyInfo (описана в [3])
Кстати, вы где примерчик взяли? Я там не нашел...
VMcL (2004-08-06 16:18:00) [10]Надо же. И всё таки я был прав в [2].
Retrieving Connection Options
Beginning with Internet Explorer 5, Internet options can be retrieved from a specific connection. To retrieve options from a particular connection, complete the following steps:
Create a INTERNET_PER_CONN_OPTION_LIST structure.
Allocate the memory for the individual Internet options that you want to retrieve from the connection.
Specify the options using INTERNET_PER_CONN_OPTION structures.
Retrieve the options using InternetQueryOption.
Utilize the option information.
Free the memory that was allocated to hold the option information using the GlobalFree function.
Aldor_ (2004-08-06 16:15:00) [11]VMcL © (06.08.04 16:10) [2]
> GlobalFree(), я полагаю.
Там параметром стоит:
HGLOBAL hMem
[in] Handle to the global memory object. This handle is returned by either the GlobalAlloc or GlobalReAlloc function.
Функция InternetQueryOption этот HGLOBAL не возвращает.
Aldor_ (2004-08-06 16:12:00) [12]TUser © (06.08.04 15:59) [1]
Пробовал делать так:
(* TInternetProxyInfo = record
dwAccessType: DWORD;
lpszProxy: LPCSTR;
lpszProxyBypass: LPCSTR;
end; *)
const
MaxStrSize: Cardinal = 1024;
var
ProxyInfo: PInternetProxyInfo;
StructSize: Cardinal;
begin
StructSize := SizeOf(TInternetProxyInfo);
GetMem(ProxyInfo, StructSize);
try
GetMem(ProxyInfo^.lpszProxy, MaxStrSize);
try
Inc(StructSize, MaxStrSize);
InternetQueryOption(nil, INTERNET_OPTION_PROXY, ProxyInfo, StructSize);
finally
FreeMem(ProxyInfo^.lpszProxy);
end;
ShowMessage(ProxyInfo^.lpszProxy);
finally
FreeMem(ProxyInfo);
end;
На выделенной строке значение ProxyInfo^.lpszProxy МЕНЯЕТСЯ! То есть функция сама присваевает этим указателям какие-то значения, а значит и сама выделят пямять под строки.
P.S. Естественно, на FreeMem(ProxyInfo^.lpszProxy); вылетает AV
VMcL (2004-08-06 16:12:00) [13]>> VMcL © (06.08.04 16:10) [2]
Хотя нет. Обманул. Вот пример из MSDN:
DWORD dwSize;
// This call determines the buffer size needed.
InternetQueryOption(NULL,INTERNET_OPTION_USER_AGENT,NULL,&dwSize);
// Allocate the necessary memory.
lpszData = new char[dwSize];
// Call InternetQueryOption again with the buffer provided.
InternetQueryOption(NULL, INTERNET_OPTION_USER_AGENT,lpszData,&dwSize);
// Insert code to user the user agent string information.
// Free the allocated memory.
delete [] lpszData;
В общем, сам буфер выделяешь, сам и освобождаешь.
VMcL (2004-08-06 16:10:00) [14]>> Aldor_ (06.08.04 15:41)
GlobalFree(), я полагаю.
TUser (2004-08-06 15:59:00) [15]В WinAPI-функции обычно передается PChar (точнее - PAnsiChar). Я тут на форуме недавно с этим разбирался. Если ф-ция должна вернуть что-то в этот буфер, то память надо выделить (размер буфера - максимальный по твоим представлениям размер результата), а потом освободить. Если же ты передаешь строку в апи-функцию (как, например, в FindWindow), то синтаксис такойже, как при работе с обычными строками, а за выделением/освобождением памяти следит компилятор (точнее - менеджер памяти).