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

Вниз

Передача строк в/из функции dll   Найти похожие ветки 

 
Aldor_   (2004-08-06 15:41) [0]

В функцию из одной из стандартных библиотек windows в качестве выходного параметра должна передаваться структура, содержащая указатели на строки.
 В описании параметра написано слелующее:
Strings returned by InternetQueryOption are globally allocated, so the calling application must free them when it is finished using them.
 Это что же получается, ОН(она) память выделяет, а Я должен ее освобождать?!
 Что означает globally allocated?
 Под саму структуру (в том числе и указатели на строки) память выделять и освобождать мне?
 И что передавать в качестве размера буфера?


 
TUser ©   (2004-08-06 15:59) [1]

В WinAPI-функции обычно передается PChar (точнее - PAnsiChar). Я тут на форуме недавно с этим разбирался. Если ф-ция должна вернуть что-то в этот буфер, то память надо выделить (размер буфера - максимальный по твоим представлениям размер результата), а потом освободить. Если же ты передаешь строку в апи-функцию (как, например, в FindWindow), то синтаксис такойже, как при работе с обычными строками, а за выделением/освобождением памяти следит компилятор (точнее - менеджер памяти).


 
VMcL ©   (2004-08-06 16:10) [2]

>>Aldor_  (06.08.04 15:41)

GlobalFree(), я полагаю.


 
Aldor_   (2004-08-06 16:12) [3]

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) [4]

>>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;


В общем, сам буфер выделяешь, сам и освобождаешь.


 
Aldor_   (2004-08-06 16:15) [5]

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 не возвращает.


 
VMcL ©   (2004-08-06 16:18) [6]

Надо же. И всё таки я был прав в [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.


 
VMcL ©   (2004-08-06 16:19) [7]

>>Aldor_  (06.08.04 16:15) [5]

Приведение типов отменили?


 
Aldor_   (2004-08-06 16:19) [8]

VMcL ©   (06.08.04 16:12) [4]
InternetQueryOption(NULL,INTERNET_OPTION_USER_AGENT,NULL,&dwSize);

Функция с ЭТИМ параметром возвращает всего лишь строку, а с INTERNET_OPTION_PROXY возвразает структуру TInternetProxyInfo (описана в [3])

Кстати, вы где примерчик взяли? Я там не нашел...


 
Aldor_   (2004-08-06 16:26) [9]

VMcL ©   (06.08.04 16:19) [7]

 Пока один отвечает, другой уже запостить успевает :)

[6]:

 Да, читал но не разобрался, понял вот так:

 Память под структуру выделяю и освобождаю сам (GetMem/FreeMem)
 Память под строки выделяет функция, но освобождаю я сам с помощью GlobalFree(HGLOBAL(PointerToString))

 Правильно?


 
VMcL ©   (2004-08-06 16:35) [10]

>>Aldor_  (06.08.04 16:26) [9]

>Правильно?

А Гейтс его знает. Почитай в справке. Там примеры есть. А вообще, как любит говорить Игорь Шевченко, "практика - критерий истины".


 
Aldor_   (2004-08-06 16:43) [11]

Спасибо за помощь!


 
Aldor_   (2004-08-07 15:11) [12]

Провел маленькое исследование.
Если вызывать функцию в таком виде:
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;

Таким образом избавляемся от "локальных" накладок, но, возможно, "глобально" эта память все еще считается занятой.

 Буду благодарен, если кто подскажет корректный вариант глобального освобождения памяти.


 
VMcL ©   (2004-08-08 12:11) [13]

>>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-08 15:09) [14]

VMcL ©   (08.08.04 12:11) [13]
> ProxyInfo^.lpszProxy указывает как раз на область памяти сразу за структурой INTERNET_PROXY_INFO

 Почему это является признаком того, что память не считается занятой "глобально"?

> Только, чтобы не "угадывать" MaxStrSize, следует писать так:

Угу, так точно, то был черновой вариант.


 
VMcL ©   (2004-08-08 16:56) [15]

>>Aldor.  (08.08.04 15:09) [14]

>Почему это является признаком того, что память не считается занятой "глобально"?

Потому что ты сам её выделил GetMem"ом.



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

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

Наверх




Память: 0.51 MB
Время: 0.024 c
1-1091723779
TeNY
2004-08-05 20:36
2004.08.22
динамичные параметры функции


3-1090828255
serg128
2004-07-26 11:50
2004.08.22
Как в ф-ции format задать разделители тысяч?


1-1091807061
Spike
2004-08-06 19:44
2004.08.22
Подскажите, как скопировать в Clipboar русский текст...


1-1091964308
Чувак
2004-08-08 15:25
2004.08.22
Проблема с переменными.


1-1091612532
П7
2004-08-04 13:42
2004.08.22
Изменение TTreeNode