Title: How to do a SafeArray Access with a DLL for Variants (OLE)
Question: I had to write some safecall procedures in Delphi for an excisting DLL in C++.
I didn't find any example on the Net nor many documentation about it. So it took me some time but here is the code that finally did the job.
In this procedure I show you how to write string arrays, matrix arrays or blob-data (like graphics) Thx to Luc for the C++ support
Now there is at least one document about SafeCalls in Delphi ;-)
Answer:
This here is a "cut-out" from demo i wrote to use the DLL demanding some
safecalls.
I added the code how to create Strings, matrix-arrays or blob safecalls
I replaced DLL-specific code with xxxxxxx. Up to you to replace it with your
code.
// ---------------------------------------------------------------------------
// OLE SAFECALL DEMO !
// ---------------------------------------------------------------------------
procedure TForm_OLEDemo.SB_ActivateClick(Sender: TObject);
var
MyConnect : Ixxxxxx; // contains pointer to the Interface dispatch
// this depends on your DLL-interface
// correct Ixxxxxx by your Interface data.
// See also further in the code for changing
MyHandle : THandle; // the handle for passing the info
pSafeHeader : PSafeArray; // needed for the SafeCall to the DLL
MyHeader : OleVariant; // will contain an array of strings
pSafeMatrix : PSafeArray; // needed for the SafeCall to the DLL
MyMatrix : Variant; // will contain an matrix array of variants
MyFileHandle : integer; // to calculate the size
iBytesRead : integer; // unused return parm
MyFileSize : integer; // needed for the byte calc
MyPtr : pointer;
MyRGSA_bound : array[0..0] of TSafeArrayBound; // needed for the SafeCall
pSafeBlob : PSafeArray; // needed for the SafeCall to the DLL
MyFileToRead : Widestring;
begin
MyFileToRead := 'C:\image.jpg'; // as an example
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// PREPARING SOME VARIABLES -
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// AN ARRAY -
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
MyHeader := VarArrayCreate([0,2], VT_BSTR);
MyHeader[0] := 'title 1';
MyHeader[1] := 'title 2';
MyHeader[2] := 'title 3';
pSafeHeader := PSafeArray(TVarData(MyHeader).VArray);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// A MIXED ARRAY -
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
MyMatrix := VarArrayCreate([0, 1, 0, 2],VT_VARIANT) ;
MyMatrix[0,0] := 1; // an integer
MyMatrix[0,1] := 'some text'; // text
MyMatrix[0,2] := now(); // date
MyMatrix[1,0] := 1;
MyMatrix[1,1] := 'more text';
MyMatrix[1,2] := now();
pSafeMatrix := PSafeArray(TVarData(MyMatrix).VArray);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// BLOB INFO (data, pictures, ...)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
MyFileHandle := FileOpen(MyFileToRead, fmOpenRead);
MyFileSize := FileSeek(MyFileHandle,0,2);
FileSeek(MyFileHandle,0,0);
MyRGSA_bound[0].lLbound := 0; // - - - - - - - - -
MyRGSA_bound[0].cElements := MyFileSize; // This is tricky !
pSafeBlob := SafeArrayCreate(VT_I1,1, MyRGSA_bound); // - - - - - - - - -
SafeArrayAccessData(pSafeBlob,MyPtr);
iBytesRead := FileRead(MyFileHandle, MyPtr^, MyFileSize);
FileClose(MyFileHandle);
SafeArrayUnAccessData(pSafeBlob);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Create OleServer Object -
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
try
MyConnect := CreateOleObject('***YOUR OWN CALL***') as Ixxxxxx;;
except
ShowMessage('Could not create an API object.'#13
'Check if the DLL has been registered on this machine?');
Exit;
end;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Activate & Handle capturing -
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
MyHandle := MyConnect.OpenDLLHandle(xxxxxx);
// * * * * * * * * * * * * * *
// Now you can use the pSafeHeader, pSafeMatrix and pSafeBlob in the
// procedures of your DLL that demands these safecalls to exchange
// the prepared data.
// * * * * * * * * * * * * * *
MyConnect.CloseDLLHandle(MyHandle,xxxxxxx);
end;