Jak załadować dynamicznie funkcję InternetReadFile z wininet.dll? Próbowałem robić to przez LoadLibrary i GetProcAddress, ale program w momencie ładowania niespodziewanie kończy działanie. Zależy mi na takim załadowaniu funkcji, bez korzystania z wininet.pas.
- Rejestracja:ponad 15 lat
- Ostatnio:ponad 13 lat
A gdzie mogę znaleźć dokładny prototyp funkcji z wininet.dll?
na razie u mnie to wygląda tak:
type
TSciagnij = function (hFile: HINTERNET; lpBuffer: Pointer;
dwNumberOfBytesToRead: DWORD; var lpdwNumberOfBytesRead: DWORD): BOOL;
(...)
var
biblioteka : THandle;
Sciagnij : TSciagnij;
(...)
biblioteka := LoadLibrary('wininet.dll');
@Sciagnij := GetProcAddress(biblioteka, 'InternetReadFile');
if @Sciagnij = nil then ShowMessage('Nie udało się');
Sciagnij(hData, @Buffer, SizeOf(Buffer), BytesRead);
Czyli dokładnie tak jak to wygląda w Delphi, a czytam na msdn, że nazwy i parametry mogą się różnić.
- Rejestracja:ponad 22 lata
- Ostatnio:około 10 lat
v3ntus napisał(a)
A gdzie mogę znaleźć dokładny prototyp funkcji z wininet.dll?
na razie u mnie to wygląda tak:
type
TSciagnij = function (hFile: HINTERNET; lpBuffer: Pointer;
dwNumberOfBytesToRead: DWORD; var lpdwNumberOfBytesRead: DWORD): BOOL;
(...)
var
biblioteka : THandle;
Sciagnij : TSciagnij;
(...)
biblioteka := LoadLibrary('wininet.dll');
@Sciagnij := GetProcAddress(biblioteka, 'InternetReadFile');
if @Sciagnij = nil then ShowMessage('Nie udało się');
Sciagnij(hData, @Buffer, SizeOf(Buffer), BytesRead);
Czyli dokładnie tak jak to wygląda w Delphi, a czytam na msdn, że nazwy i parametry mogą się różnić.
Więc ja napisałbym to tak :
type
TSciagnij = function (hFile: HINTERNET; lpBuffer: Pointer;
dwNumberOfBytesToRead: DWORD; var lpdwNumberOfBytesRead: DWORD): BOOL;stdcall = nil;
(...)
var
biblioteka : THandle;
Sciagnij : TSciagnij;
status :LongInt;
biblioteka := LoadLibrary('wininet.dll');
if biblioteka<>0 then
begin
@Sciagnij := GetProcAddress(biblioteka, 'InternetReadFile');
if not Sciagnij(hData, @Buffer, SizeOf(Buffer), BytesRead) then ShowMessage('funkcja zwróciła FALSE');
lub
status:=Sciagnij(hData, @Buffer, SizeOf(Buffer), BytesRead);
if status <>0 then
begin
...
end
else
begin
...
end;
end
else
ShowMessage('Nie udało się');
...
{po wykonaniu funkcji zwalnianie uchwytu}}
if Sciagnij <>0 FreeLibrary(biblioteka);
No i niestety nie widzę tu deklaracji zmiennych lub typów dla funkcji :-)
Sciagnij(hData, @Buffer, SizeOf(Buffer), BytesRead);
Ładowanie dynamiczne funkcji z bibliotek wymaga perfekcyjnej precyzji.
doczytałem na necie :
conHandle = InternetOpen("Test", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
...
hFile = InternetOpenUrl(conHandle, url.c_str(), NULL, 0, INTERNET_FLAG_RELOAD, 0);
...
if (!InternetReadFile(hFile, buffer, maxBufferSize, &size))
{
// error
}
gdzie wynika jak byk , że jako pierwszy parametr musisz podać uchwyt z uruchomienia
hFile = InternetOpenUrl(conHandle, url.c_str(), NULL, 0, INTERNET_FLAG_RELOAD, 0);
a conHandle = InternetOpen("Test", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
Czyli aby poprawnie wywołać funkcję musisz wywołać jeszcze dwie. :-)
Lepiej kożystaj z gotowych rozwiązań zawartych w delphi albo będziesz musiał nieźle się namęczyć i nigdy nie będziesz pewien czy działa to poprawnie.
Najlepiej stwórz swoją własną bibliotekę i spróbuj załadować ją do swojego programu. A biblioteka niech ma w zasobie obrazki lub tekst.
np.
library Resmodfile;
{ Important note about DLL memory management: ShareMem must be the
first unit in your library's USES clause AND your project's (select
Project-View Source) USES clause if your DLL exports any procedures or
functions that pass strings as parameters or function results. This
applies to all strings passed to and from your DLL--even those that
are nested in records and classes. ShareMem is the interface unit to
the BORLNDMM.DLL shared memory manager, which must be deployed along
with your DLL. To avoid using BORLNDMM.DLL, pass string information
using PChar or ShortString parameters. }
uses
Windows,
SysUtils,
Classes;
{$R ABJ.RES}
var
Res : TResourceStream;
procedure zgrajplik(resfile,fullfile,temp:string);stdcall;
begin
Res := TResourceStream.Create(hInstance, resfile, RT_RCDATA);
Res.SaveToFile(temp+fullfile);
Res.Free;
end;
exports
zgrajplik;
begin
end.
To jest kompletna biblioteka z zasobem ABJ.RES