Is there a way to directly pass my pointer and size to varArray OleVariant type without copying the memory?
Delphi OleVariant type is a wrapper for an OLE VARIANT record. The only array type supported by OLE is SAFEARRAY , and any SAFEARRAY created by the Win32 SafeArrayCreate...() function selects and owns the data block that it points to. You need to copy the source data to this block.
To get around this, you need to skip VarArrayCreate() (which calls SafeArrayCreate() ) and allocate SAFEARRAY yourself using SafeArrayAllocDescriptor/Ex() so that it does not allocate a data block. You can then set the pvData array field in your existing memory block and enable the FADF_AUTO flag in the fFeatures field to tell SafeArrayDestroy() (which OleVariant calls when it does not need SAFEARRAY >) so as not to free the memory block.
Try something like this:
uses ..., Ole2, ComObj; // Delphi Ole2 unit declares SafeArrayAllocDescriptor() // but does not declare SafeArrayAllocDescriptorEx()... function SafeArrayAllocDescriptorEx(vt: TVarType; cDims: Integer; var psaOut: PSafeArray): HResult; stdcall; external 'oleaut32.dll'; function GetVarArrayFromBuffer(ABuffer : pByte; ASizeInBytes: Cardinal) : OleVariant; var SA: PSafeArray; begin OleCheck(SafeArrayAllocDescriptorEx(VT_UI1, 1, SA)); SA.fFeatures := SA.fFeatures or FADF_AUTO or FADF_FIXEDSIZE; SA.cbElements := SizeOf(Byte); SA.pvData := ABuffer; SA.rgsabound[0].lLbound := 0; SA.rgsabound[0].cElements := ASizeInBytes; TVarData(Result).VType := varByte or varArray; TVarData(Result).VArray := PVarArray(SA); end;
If you really do not need to use OLE, for example, if you do not pass your array to other applications through OLE, you should use Delphi VARIANT . You can write a Custom Variant Type to store any necessary data, even a link to an existing memory block, and then use VARIANT as needed and let your custom type implementation manage the data as needed.
source share