【问题标题】:C# function doesn't update SAFEARRAYC# 函数不更新 SAFEARRAY
【发布时间】:2012-12-07 18:58:31
【问题描述】:

我有一个带有以下签名的 C# 函数:

int Get1251Bytes(string source, byte[] result, Int32 lengthOfResult)

我从 C++ 中调用它。编译器告知我第二个参数必须具有SAFEARRAY* 类型。所以我这样称呼它:

SAFEARRAY* safeArray = SafeArrayCreateVector(VT_UI1, 0, arrayLength);
char str[] = {'s', 't', 'a', 'c', 'k', '\0'};
converter->Get1251Bytes(str, safeArray, arrayLength);

但是 safeArray 没有更新,它仍然包含 zores。但我在 C# 单元测试中测试了Get1251Bytes 函数。它可以正常工作并更新result 数组。我做错了什么?

【问题讨论】:

  • 我对 C# 了解 zero,但是 byte[] result 是否需要作为 ref 类型传入(如果您打算更新,也需要使用 lengthOfResult它也是)?
  • 我没有,我想。数组是 C# 中的引用类型,我不会更改数组的引用本身(只是编辑元素的值)。在这种情况下,它应该通过引用进行更新。
  • 值得一试。就像我说的,关于 C# 的 zilch 知识。有趣的问题。

标签: c# c++ com safearray


【解决方案1】:

即使使用 Array,您也必须使用 refout。你应该使用out

int Get1251Bytes(string source, out byte[] result, Int32 lengthOfResult)
{
    ...
}

有关outref lokk 的更多信息,请访问链接。

这里是关于arrays的文章

【讨论】:

  • outref 关键字用于允许更改引用本身(new 关键字)。我的函数不会改变数组的引用,它只是改变元素值)。
【解决方案2】:

您的问题与Blittable and Non-Blittable Types 有关(Byte 是 blittable):

作为一种优化,仅包含 blittable 成员的 blittable 类型和类的数组在编组期间被固定而不是复制。当调用者和被调用者在同一个单元中时,这些类型可以作为 In/Out 参数编组。但是,这些类型实际上是作为 In 参数编组的,如果要将参数编组为 In/Out 参数,则必须应用 InAttribute 和 OutAttribute 属性。

要修复您的代码,您需要将 [Out] 属性应用于 C# 代码中的 result 参数:

int Get1251Bytes(string source, [Out] byte[] result, Int32 lengthOfResult)

另外,您不需要传递lengthOfResult。在 .NET 中,您可以使用 Length 属性来获取数组的大小。

【讨论】:

  • 感谢您的参考。但我在byte[] result 之前尝试了[Out][In, Out] 属性——数组仍然被0 填充。
  • @Zharro:我创建了一个示例,重现了您的问题并通过应用 [Out] 属性解决了该问题。对我来说看起来有点奇怪的一件事是你传递字符串的方式。我希望非托管参数类型是BSTR 而不是char[],因为您似乎正在使用。在我的示例中,我使用SysAllocString 创建一个正确的BSTR,然后通过它。如果您启用混合模式调试,您也可以在托管代码中设置断点,以验证您的参数是否正确传递。
  • 执行我!我忘记在接口的 Get1251Bytes 的签名中指定这个属性。非常感谢!
猜你喜欢
  • 2021-09-22
  • 2012-08-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-06-19
  • 2013-09-12
相关资源
最近更新 更多