我可以在不复制的情况下从缓冲区 (pByte) 和大小创建 VarArray OleVariant 吗?
Can I create a VarArray OleVariant from a buffer (pByte) and size without copying?
我可以将内存从缓冲区复制到安全数组中,如下所示
function GetVarArrayFromBuffer(ABuffer : pByte; ASizeInBytes: Cardinal) : OleVariant;
var
LVarArrayPtr: Pointer;
begin
Result := VarArrayCreate([0, ASizeInBytes - 1], varByte);
LVarArrayPtr := VarArrayLock(Result);
try
Move(ABuffer^, LVarArrayPtr^, ASizeInBytes);
finally
VarArrayUnLock(Result);
end;
end;
但是,有没有办法直接将我的指针和大小传递给 varArray
类型 OleVariant
而无需复制内存?
[编辑]
我可以看到 OleVariant
中的数组是一个 SAFEARRAY
(定义为 PVarArray = ^TVarArray
),因此似乎应该有一种方法可以通过填充TVarArray
中的值并在 OleVariant
.
中设置 VType
和 VArray
值
您或许可以通过破解获得包含数组数据的 OleVariant,而无需复制它。
但是,当 OleVariant 变量超出范围时,您将遇到一个问题。
RTL 将在 oleaut32.dll 中调用 SafeArrayDestroy 来销毁与安全数组关联的内存,这将失败,因为内存并非来自 Windows 预期的位置。
is there a way to directly pass my pointer and size into a varArray type OleVariant without copying memory?
Delphi 的 OleVariant
type is a wrapper for OLE's VARIANT
record. The only type of array that OLE supports is SAFEARRAY
和任何由 Win32 SafeArrayCreate...()
函数创建的 SAFEARRAY
分配并拥有它指向的数据块。您必须将源数据复制到该块中。
要绕过它,您必须跳过 VarArrayCreate()
(调用 SafeArrayCreate()
)并使用 SafeArrayAllocDescriptor/Ex()
自己分配 SAFEARRAY
,这样它就不会分配数据堵塞。然后你可以设置数组的 pvData
字段指向你现有的内存块,并在它的 fFeatures
字段中启用 FADF_AUTO
标志来告诉 SafeArrayDestroy()
(哪个 OleVariant
不再需要 SAFEARRAY
时调用)不释放内存块。
尝试这样的事情:
uses
..., Ole2, ComObj;
// Delphi's 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;
如果您实际上不需要使用 OLE,例如您不通过 OLE 将您的数组传递给其他人的应用程序,那么您应该使用 Delphi 的 Variant
type instead. You can write a Custom Variant Type
来保存无论您想要什么数据,甚至是对现有内存块的引用,然后根据需要使用 Variant
并让您的自定义类型实现根据需要管理数据。
我可以将内存从缓冲区复制到安全数组中,如下所示
function GetVarArrayFromBuffer(ABuffer : pByte; ASizeInBytes: Cardinal) : OleVariant;
var
LVarArrayPtr: Pointer;
begin
Result := VarArrayCreate([0, ASizeInBytes - 1], varByte);
LVarArrayPtr := VarArrayLock(Result);
try
Move(ABuffer^, LVarArrayPtr^, ASizeInBytes);
finally
VarArrayUnLock(Result);
end;
end;
但是,有没有办法直接将我的指针和大小传递给 varArray
类型 OleVariant
而无需复制内存?
[编辑]
我可以看到 OleVariant
中的数组是一个 SAFEARRAY
(定义为 PVarArray = ^TVarArray
),因此似乎应该有一种方法可以通过填充TVarArray
中的值并在 OleVariant
.
VType
和 VArray
值
您或许可以通过破解获得包含数组数据的 OleVariant,而无需复制它。
但是,当 OleVariant 变量超出范围时,您将遇到一个问题。
RTL 将在 oleaut32.dll 中调用 SafeArrayDestroy 来销毁与安全数组关联的内存,这将失败,因为内存并非来自 Windows 预期的位置。
is there a way to directly pass my pointer and size into a varArray type OleVariant without copying memory?
Delphi 的 OleVariant
type is a wrapper for OLE's VARIANT
record. The only type of array that OLE supports is SAFEARRAY
和任何由 Win32 SafeArrayCreate...()
函数创建的 SAFEARRAY
分配并拥有它指向的数据块。您必须将源数据复制到该块中。
要绕过它,您必须跳过 VarArrayCreate()
(调用 SafeArrayCreate()
)并使用 SafeArrayAllocDescriptor/Ex()
自己分配 SAFEARRAY
,这样它就不会分配数据堵塞。然后你可以设置数组的 pvData
字段指向你现有的内存块,并在它的 fFeatures
字段中启用 FADF_AUTO
标志来告诉 SafeArrayDestroy()
(哪个 OleVariant
不再需要 SAFEARRAY
时调用)不释放内存块。
尝试这样的事情:
uses
..., Ole2, ComObj;
// Delphi's 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;
如果您实际上不需要使用 OLE,例如您不通过 OLE 将您的数组传递给其他人的应用程序,那么您应该使用 Delphi 的 Variant
type instead. You can write a Custom Variant Type
来保存无论您想要什么数据,甚至是对现有内存块的引用,然后根据需要使用 Variant
并让您的自定义类型实现根据需要管理数据。