微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何将结构数组正确转换为.Net中的IntPtr

如何解决如何将结构数组正确转换为.Net中的IntPtr

我在C ++中具有结构

struct {
      CF_OPERATION_TRANSFER_PLACEHOLDERS_FLAGS Flags;
      NTSTATUS                                 CompletionStatus;
      LARGE_INTEGER                            PlaceholderTotalCount;
      CF_PLACEHOLDER_CREATE_INFO               *PlaceholderArray;
      DWORD                                    PlaceholderCount;
      DWORD                                    EntriesProcessed;
    } TransferPlaceholders;

并将其编组到.Net:

[StructLayout(LayoutKind.Sequential)]
            public struct TRANSFERPLACEHOLDERS
            {
                /// <summary>Flags for transferring placeholders.</summary>
                public CF_OPERATION_TRANSFER_PLACEHOLDERS_FLAGS Flags;

                /// <summary>The completion status of the operation.</summary>
                public NTStatus CompletionStatus;

                /// <summary>Total number of placeholders.</summary>
                public long PlaceholderTotalCount;

                /// <summary>An array of placeholders to be transferred.</summary>
                public IntPtr PlaceholderArray;

                /// <summary>The number of placeholders being transferred.</summary>
                public uint PlaceholderCount;

                /// <summary>The placeholder entries that have been processed.</summary>
                public uint EntriesProcessed;

            }

CF_PLACEHOLDER_CREATE_INFO编组:

[PInvokeData("cfapi.h",MSDNShortId = "2DC1FF5F-FBFD-45CA-8CD5-B2F586C22778")]
        [StructLayout(LayoutKind.Sequential)]
        public struct CF_PLACEHOLDER_CREATE_INFO
        {
            /// <summary>The name of the child placeholder file or directory to be created.</summary>
            [MarshalAs(UnmanagedType.LPWStr)] 
            public string RelativeFileName;

            /// <summary>File system Metadata to be created with the placeholder.</summary>
            public CF_FS_MetaDATA FsMetadata;

            /// <summary>
            /// A user mode buffer containing file information supplied by the sync provider. This is required for files (not for directories).
            /// </summary>
            public IntPtr FileIdentity;

            /// <summary>Length,in bytes,of the <c>FileIdentity</c>.</summary>
            public uint FileIdentityLength;

            /// <summary>Flags for specifying placeholder creation behavior.</summary>
            public CF_PLACEHOLDER_CREATE_FLAGS Flags;

            /// <summary>The result of placeholder creation. On successful creation,the value is: STATUS_OK.</summary>
            public HRESULT Result;

            /// <summary>The final USN value after create actions are performed.</summary>
            public int CreateUsn;
        }

因此,我需要将结构CF_PLACEHOLDER_CREATE_INFO的数组传递给IntPtr PlaceholderArray。 我试图通过这种方式转换结构数组:

aPlaceholders.MarshalToPtr(Marshal.AllocHGlobal,out _);

但是我只接收数组第一个元素的指针。因此,如果数组大小为1,则可以使用。否则,我将收到Acess Violation 0xFFFFFFFFFFFFFF。 还试图使用此功能一张一张地复制数组的每个元素:

public void MarshalUnmananagedArray2Struct<T>(IntPtr unmanagedArray,int length,out T[] mangagedArray)
        {
            var size = Marshal.SizeOf(typeof(T));
            mangagedArray = new T[length];

            for (int i = 0; i < length; i++)
            {
                IntPtr ins = new IntPtr(unmanagedArray.ToInt64() + i * size);
                mangagedArray[i] = Marshal.PtrToStructure<T>(ins);
            }
        }

并且具有绝对相同的行为,仅在数组大小为1的情况下有效。 我猜我在将数组转换为IntPtr时做错了。会很高兴为您提供帮助!

编辑: MarshalToPtr方法的源代码

public static IntPtr MarshalToPtr<T> (this IEnumerable<T> items,Func<int,IntPtr> memAlloc,out int bytesAllocated,int prefixBytes = 0)
{
    if (!typeof (T).IsMarshalable ()) throw new ArgumentException (@"Structure layout is not sequential or explicit.");
    
    bytesAllocated = prefixBytes;
    
    var count = items?.Count () ?? 0;
    
    if (count == 0) return memAlloc (bytesAllocated);

    var sz = Marshal.SizeOf (typeof (T));
    bytesAllocated += sz * count;
    
    var result = memAlloc (bytesAllocated);
    result.Write (items,prefixBytes,bytesAllocated);

    return result;
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。