我有从 C# 调用以下 COM 方法,该方法在提供的缓冲区中返回一个字符串pchText
(这是not必须以零结尾)和复制的字符数pcch
:
HRESULT Next([in, out] long* pcch, [out, size_is(*pcch)] OLECHAR* pchText);
如何定义互操作的 C# 签名?
到目前为止,我尝试过这个:
void Next(ref int pcch,
[MarshalAs(UnmanagedType.LPWStr, SizeParamIndex = 0)]
System.Text.StringBuilder pchText);
它似乎有效,但我不确定是否有效SizeParamIndex
有任何影响StringBuilder
.
嗯,正确调用它确实是一个困难的函数。您的声明大致没问题,您只需要应用 [PreserveSig] 属性并设置返回值类型int因此您可以发现 S_FALSE 返回值指示没有下一个元素。
困难在于必须预先猜测要传递的 StringBuilder 有多大。本机代码在 GC 堆中获取一个原始指针,指向构建器缓冲区,因此事故是相当致命的。您必须预先猜测构建器的正确容量并将其作为初始值传递pcch争论。
编组员does注意函数返回后的SizeParamIndex。它只会复制尽可能多的字符ppch表示。如果由于某种原因写入的内容超出了缓冲区的容量,那么程序将立即中止并抛出 ExecutionEngineException 异常,因为这表明 GC 堆已损坏。
请注意,如果您猜测的容量太低,那么您不一定能发现这一点。当函数仅复制适合的字符并且不返回错误代码时,您可能会得到一个被截断的字符串。找出这是否是问题的最佳方法是通过测试并有意通过小型构建器。注意返回值。
有一个怪癖值得指出,该函数签名遇到了 COM 早期常见的黑客行为,实际上通过 OLECHAR* 返回二进制数据而不是文本。强烈提示就是这种情况,因为不能保证字符串以零结尾。这在 .NET 中不会有好结果,当字符串标准化时,数据将被损坏。当数据恰好与 utf-16 代理字符之一匹配时,程序就会崩溃。如果是这种情况,那么您需要一个 Short[] 而不是 StringBuilder。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)