【发布时间】:2021-12-08 13:01:45
【问题描述】:
我似乎无法在从 COM C++ 程序填充的 C# 程序中获取字节数组。 C# 程序包含对 C++ DLL 的引用,并通过以下方式实例化:
_wiCore = new WebInspectorCoreLib.WICore();
实际调用
uint imageSize = *image byte count*; // set to size of image being retrieved
var arr = new byte[imageSize];
_wiCore.GetFlawImage(1, 0, ref imageSize, out arr);
C++ IDL:
[id(5)] HRESULT GetFlawImage([in] ULONG flawID, [in] USHORT station, [in, out] ULONG *pImageSize, [out] BYTE *pImageBytes);
这会正确返回图像大小,但数组中没有任何内容。我还尝试了签名(pImageBytes 的额外间接级别):
[id(5)] HRESULT GetFlawImage([in] ULONG flawID, [in] USHORT station, [in, out] ULONG *pImageSize, [out] BYTE **pImageBytes);
在 C# 中传入一个 IntPtr,但这会返回包含图像字节地址的内存地址,而不是图像字节。
对我做错了什么有什么想法吗?
【问题讨论】:
-
也许您需要将 C# 内存提供给 C++ 来填充?
-
当 COM 调用需要返回动态分配的内存时,您不能使用 c++ 堆,因此不要使用 new 来分配图像内存,请使用 ::CoTaskMemAlloc docs.microsoft.com/en-us/windows/win32/api/combaseapi/…。另一种选择是返回一个安全的字节数组:docs.microsoft.com/en-us/archive/msdn-magazine/2017/march/…
-
你为什么不使用
SAFEARRAY?然后将其声明为retval而不是out -
我同意@Charlieface 的观点——
SAFEARRAY是唯一在 COM 中表示数组的正确方法。您最终可能想要使用 DCOM,然后尝试将指针传递给多个数据,这将严重破坏,而 SAFEARRAY 会正常工作。 -
@BenVoigt - 这不是真的。您基本上可以在 COM 中使用任何类型(如果使用是进程外的,您必须注意输入/输出/等注释和/或提供代理存根)。事实是,高级语言(阅读:不同于 C/C++)通常更容易使用自动化类型(VARIANT 类型等)。