I’m a bit puzzled as to how Pointers should be properly used in my scenario. I have a DLL with some embedded resources in it. I expose a function in this DLL which passes binary data of one of those resources back to its calling app. In this case, I’ve embedded a JPG image file. My DLL does properly load the file into a resource stream. However from there, the passing it back to the app gets messy.
Here’s my DLL’s code (with a JPG loaded and named SOMERESOURCE):
library ResDLL;
{$R *.dres}
uses
System.SysUtils,
System.Classes,
Winapi.Windows;
{$R *.res}
function GetResource(const ResName: PChar; Buffer: Pointer;
var Length: Integer): Bool; stdcall;
var
S: TResourceStream;
L: Integer;
Data: array of Byte;
begin
Result:= False;
try
S:= TResourceStream.Create(HInstance, UpperCase(ResName), RT_RCDATA);
try
S.Position:= 0;
L:= S.Size;
Length:= L;
SetLength(Data, L);
S.Read(Data[0], L);
Buffer:= @Data[0];
Result:= True;
finally
S.Free;
end;
except
Result:= False;
end;
end;
exports
GetResource;
begin
end.
And here’s my app’s code (with just a TBitBtn and TImage):
function GetResource(const ResName: PChar; Buffer: Pointer;
var Length: Integer): Bool; stdcall; external 'ResDLL.dll';
procedure TForm1.BitBtn1Click(Sender: TObject);
var
Buffer: array of Byte;
Size: Integer;
S: TMemoryStream;
P: TPicture;
begin
if GetResource('SOMERESOURCE', @Buffer[0], Size) then begin
S:= TMemoryStream.Create;
try
SetLength(Buffer, Size);
S.Write(Buffer, Size);
S.Position:= 0;
P:= TPicture.Create;
try
P.Graphic.LoadFromStream(S);
Image1.Picture.Assign(P);
finally
P.Free;
end;
finally
S.Free;
end;
end else begin
raise Exception.Create('Problem calling DLL');
end;
end;
It appears as if the whole DLL call is successful, however the data which was received is empty (full of 0’s). I am full of curiosity as to how something like Data would need to be called as Data[0], and in what scenarios I should, and also in what scenarios I need to use @Data. I wrote that code in the DLL entirely, and I’m not familiar with such work, so I’m sure I botched it up somewhere. Where am I going wrong?
On the DLL side,
GetResource()is reading the resource data into a local array and not copying it into the buffer that is passed to the function. Assigning the local array to theBufferpointer does not copy the data being pointed at.On the app side,
BitBtn1Click()is not allocating any memory forGetResource()to write the resource data into. Even if it were, you are not writing the buffer into theTMemoryStreamcorrectly. Even if you were, you are not loading theTMemoryStreaminto theTPicturecorrectly.You have a couple of approaches you can take to fix the Buffer issue:
1) have
GetResource()allocate a buffer and return it to the app, then have the app pass the buffer back to the DLL when finished to free it:.
2) have the app query the DLL for the size of the resource, then allocate a buffer and pass it to the DLL to fill in:
.
Or:
.