How do I marshall a pointer to a pointer of an array of structures?

后端 未结 2 1279
盖世英雄少女心
盖世英雄少女心 2020-12-10 14:59

My C declarations are as follows:

int myData(uint myHandle, tchar *dataName, long *Time, uint *maxData, DATASTRUCT **data);

typedef struct {
  byte Rel;
  _         


        
2条回答
  •  挽巷
    挽巷 (楼主)
    2020-12-10 15:07

    Okay, it seems as though your native library does the allocation, so really all you need to do is provide a pointer through which you can access the allocated data.

    Change your API definition to (note, I changed the maxData param to uint, long is 64 bits in .NET and 32 bits in native.

    [DllImportAttribute("myData.dll", EntryPoint = "myData")]
    public static extern int myData(uint myHandle, [MarshalAs(UnmanagedType.LPTStr)] string dataName, out uint Time, out uint maxData, out IntPtr pData);
    

    Off the top of my head I can't quite remember if you need the out keyword for the final parameter, but I think so.

    Then, call myData:

    uint nAllocs = 0, time = 0;
    IntPtr pAllocs = IntPtr.Zero;
    myData(1, "description", out time, out nAllocs, out pAllocs);
    

    Now, pAllocs should point to unmanaged memory, to marshal these into managed memory isn't too difficult:

    [StructLayoutAttribute(LayoutKind.Sequential, Pack = 1)]
    public struct DATASTRUCT
    {
        public byte Rel;
        public long Time;
        public byte Validated;
        public IntPtr Data; //pointer to unmanaged string.
    }
    
    
    int szStruct = Marshal.SizeOf(typeof(DATASTRUCT));
    DATASTRUCT[] localStructs = new DATASTRUCT[nAllocs];
    for(uint i = 0; i < nallocs; i++)
        localStructs[i] = (DATASTRUCT)Marshal.PtrToStructure(new IntPtr(pAllocs.ToInt32() + (szStruct * i)), typeof(DATASTRUCT));
    

    And now you should have an array of local structs.

    A point to note You may need to set your project to compile as x86, to standardize the size of an IntPtr to 4 bytes (DWORD) instead of AnyCPU's default 8.

提交回复
热议问题