c# - 将 safearray 的 safearray 从 C++ 中的 VARIANT 编码到 C#

标签 c# c++ native marshalling

我正在尝试从 native 库调用 .NET 中的函数,如下所示:

typedef int (WINAPI* TGetAllObjects)(int hModel, VARIANT& objects);

如果您在 C++ 客户端中调用它,调试器会显示对象是 VARIANT 的安全数组。 ,以及每个VARIANTBSTR 的安全数组.

我尝试在 C# 中实现如下:

public delegate TRetCode TGetAllObjects(int hModel, 
    [Out,In,MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT )] ref MyStruct[] objects);

[StructLayout(LayoutKind.Sequential)]
public struct MyStruct
{
    [MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)]
    public string[] Objects;
}

调用该方法时,报错:

System.Runtime.InteropServices.SafeArrayTypeMismatchException: "Specified array was not of the expected type."

请告诉我在这种情况下如何正确组织数据编码。

最佳答案

尝试:

[UnmanagedFunctionPointer(CallingConvention.StdCall)]
delegate int TGetAllObjects(int hModel, ref object objects); 

并准确查看您收到的内容。 objects 变量是 VARIANT,而不是 SAFEARRAYVARIANT& 对象包含SAFEARRAY,它不是SAFEARRAY

然后在代码中您可以检查其类型并进行强制转换。

啊,请注意 CallingConvention(WINAPIStdCall)。

我已经做了一些测试,看来基本的 VARIANT “容器”已正确通过。我会说实话,我认为 VARIANTSAFEARRAYBSTRSAFEARRAY 是一种武器,应列入《日内瓦公约》禁用名单。

更多的测试让我认为我的解决方案是最简单的。我无法直接接受/传递 object[]string[],并且接收到的 objects object[],其中每个元素都是一个string[]。像这样的东西:

var objects = new object[] { new string[] { "A", "B" }, new string[] { "C", "D" } };

你的“选角”问题

SAFEARRAY 可以有第一个元素的索引 != 0 (这是为了支持使用基于 1 的数组的 VB,数组中第一个元素为 1) 。 .NET 在“奇怪的数组”类别中确实支持这一点。多维数组 (string[1, 2]) 和基于非 0 的数组就属于这一类,处理起来很麻烦。基于非零的数组更是如此。

根据您的情况转换数组的代码(其中“转换”的意思是:将其复制到标准 .NET 数组数组):

object[] castedObjects = (object[])objects;
string[][] strings = new string[castedObjects.Length][];

for (int i = 0; i < castedObjects.Length; i++)
{
    Array ar = (Array)castedObjects[i];
    string[] ar2 = new string[ar.Length];
    Array.Copy(ar, ar2, ar2.Length);
    strings[i] = ar2;
}

关于c# - 将 safearray 的 safearray 从 C++ 中的 VARIANT 编码到 C#,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66011800/

相关文章:

java - 编译时没有库 [LWJGL]

c# - web请求如何检查用户是否成功登录

c# - dotnet restore fail "Unable to resolve ' PCLLibrary' for '.NETCoreApp,Version=v1.0'。”

c++ - 迭代最近点算法编译过程中遇到错误

c++ - gcc 是否会优化对同一变量的重复函数调用,每次调用都具有相同的输出?

javascript - React Native listView 项目删除未正确删除项目

c# - 为什么选项卡页面主体不使用 .NET 选项卡控件进行更新?

c# - 断言表达式

c++ - 如何在 iOS Objective-C 中捕获 C++ 异常代码?

android - 调用 Picture.writeToStream() 时 Android 4.3 中的 native 崩溃