如何从 C# 将双指针传递给 COM 并在 COM 中初始化它
Posted
技术标签:
【中文标题】如何从 C# 将双指针传递给 COM 并在 COM 中初始化它【英文标题】:How to pass double pointer to COM from C# and initliaze it inside COM 【发布时间】:2013-10-31 16:06:49 【问题描述】:我创建了一个采用双指针 (BYTE**) 的 COM 方法。在 COM 内部,我正在分配内存并对其进行初始化。
签名是;
HRESULT Canny([in] BSTR szLogoPath, [out] BYTE** pBuffer, [out] USHORT* iBufLen);
问题是当我从 C# 项目调用它时 COM 崩溃,而当我从 WIN32 项目调用它时它工作正常。
此外,在 C# 项目中,上述方法显示为; (BYTE** 显示为 IntPtr)
public virtual void Canny(string szLogoPath,IntPtr pBuffer, out ushort iBufLen);
我的 C# 代码是
LogoFinderClass libCOM = new LogoFinderClass();
unsafe
byte* buf = null;
IntPtr interopPtr = new IntPtr(&buf);
libCOM.Canny(@"..\Logo.bmp", interopPtr, out bufLen);
在 C++ 中,我将内存分配为;
::Canny(BSTR szLogoPath, BYTE** pBuffer, USHORT* iBufLen)
*pBuffer = new BYTE[1024];
..
从 C# 调用时,COM 在分配内存时崩溃。
【问题讨论】:
在 COM 互操作中使用 new 运算符总是错误的。客户端代码没有希望调用正确的 delete 运算符,需要 CoTaskMemAlloc。如果它快速崩溃,那么您很可能会破坏堆。对于像 Canny 这样的图像处理操作来说,1024 字节听起来太低了。 谢谢@HansPassant,我现在正在使用 CoTaskMemAlloc () 并且工作正常,但是 Marshal.Copy(..) 没有复制我在 COM 中分配的字节数,就像我正在分配8000 字节,但它正在复制大约 5000 字节,我认为 IntPtr 在某处损坏。 是的 1024 是精明操作的两个低点,我刚才提到它是虚拟值 Passing byte array between C++ and C# ByRef raises AccessViolationException的可能重复 【参考方案1】:这里不需要unsafe
。您确实需要在 C# 结束时更改函数的声明。缓冲区参数需要声明为:
ref IntPtr pBuffer
然后,调用该函数后,使用Marshal.Copy
读出缓冲区的内容。
我不是从 C# 消费 COM 的出口,但第一个参数不应该有[MarshalAs(UnmanagedType.BStr)]
吗?
另外,如果您使用CoTaskMemAlloc
而不是new
,您可以让调用者释放缓冲区,而不必导出释放器。我相信您确实导出了释放器?
【讨论】:
感谢@David 的回复。请您告诉我如何在 C# 端编辑函数声明,因为解决方案资源管理器中引用过滤器下的 lib (COM) 没有公开任何属性来编辑其签名。 @SKAR 正如我所说,我不是 C# 的 COM 专家。所以,我不知道VS中的细节。对不起。但肯定有 C# 源代码声明接口的地方? 感谢@David,使用 CoTaskMemAlloc(..) 分配内存时 COM 没有崩溃,但 Marshal.Copy(..) 没有复制我在 COM 中分配的字节数,就像我一样我正在分配 8000 字节,但它正在复制大约 5000 字节,我认为 IntPtr 在某处损坏。但是从 WIN32 调用时它再次工作正常:( @SKAR 使用new[]
没有问题。这不会导致崩溃。它只是强制你导出一个释放器。至于您的其余评论,听起来您的代码中某处存在错误。
谢谢@David,你能举个例子吗?以上是关于如何从 C# 将双指针传递给 COM 并在 COM 中初始化它的主要内容,如果未能解决你的问题,请参考以下文章