1

在我的应用程序中,需要使用 P/Invoke 将绝对任意的对象/结构传递给 C++ 函数。根据 Internet,任何对象都可以作为 C++ 结构传递(它们在调用期间被固定到特定的内存位置)。由于我只对数据感兴趣,不打算调用任何方法,这很好地满足了我的需求。但是,实验表明这些对象必须具有[StructLayout(LayoutKind.Sequential)]属性,否则代码将无法编译。不幸的是,这些类是由其他开发人员创建的,并且不保证具有此属性。

要解决此问题,一种解决方案是将对象传递给特殊的 C# 包装函数,该函数将:

  1. 使用检索对象的属性Type.GetProperties
  2. 动态创建具有必要属性的结构并从对象复制值。
  3. 添加[StructLayout(LayoutKind.Sequential)]属性。
  4. 将此结构与在步骤 1 中检索到的元数据一起传递给 C++(以便 C++ 知道什么是对象结构以及如何读取它)

由于我是 C# 新手,我不确定如何动态创建具有任意属性和属性的结构。到目前为止,我发现的是MakeGenericTypeExpandoObject,但需要的是创建一个以前未在任何地方定义的动态结构 - 甚至不是作为通用对象。有任何想法吗?

4

1 回答 1

1

像这样的东西对你有用吗?

    [StructLayout(LayoutKind.Sequential)]
    struct MyStruct
    {
        public int Size;
        public IntPtr PtrToArrayOfMetadata;
        public IntPtr PtrToArrayOfObjects;
    }

    public enum Type
    {
        Int, 
        Float,
        Decimal
    }

然后发送一个“动态”对象

        Type[] metadata = new Type[2];
        metadata[0] = Type.Int;
        metadata[1] = Type.Float;

        object[] obj = new object[2];
        obj[0] = 2;
        obj[1]= 1;

        GCHandle objHandle = GCHandle.Alloc(obj, GCHandleType.WeakTrackResurrection);
        IntPtr ptrObj = GCHandle.ToIntPtr(objHandle);

        objHandle = GCHandle.Alloc(metadata, GCHandleType.WeakTrackResurrection);
        IntPtr ptrMeta = GCHandle.ToIntPtr(objHandle);

        MyStruct tmp = new MyStruct();
        tmp.Size = 2;
        tmp.PtrToArrayOfMetadata = ptrMeta;
        tmp.PtrToArrayOfObjects = ptrObj;
于 2013-02-26T10:51:28.110 回答