0

I want to transfer one of the structures from the DXGI library, but I ran into a problem. The target structure contains a pointer to an array of structures, in the second after, where the first indicates the size of this array. And I would not want to work directly with a pointer to an array, but with the help of a marshalller, do what is required.

I tried to do it like this:

[StructLayout(LayoutKind.Sequential)]
public struct PresentParameters
{
    public uint DirtyRectsCount { get; set; }
    [field: MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.Struct, SizeParamIndex = 0)]
    public Rect[] DirtyRects { get; set; }
    [field: MarshalAs(UnmanagedType.LPStruct)]
    public Rect ScrollRect { get; set; }
    [field: MarshalAs(UnmanagedType.LPStruct)]
    public Point ScrollOffset { get; set; }
}

But the original structure looks like this:

typedef struct DXGI_PRESENT_PARAMETERS
{
    UINT DirtyRectsCount;
    /* [annotation] */ 
    _Field_size_full_opt_(DirtyRectsCount)  RECT *pDirtyRects;
    RECT *pScrollRect;
    POINT *pScrollOffset;
} DXGI_PRESENT_PARAMETERS;

Is it possible to do this, or is it worth describing a custom marshaller who would do this?

2
  • 2
    Probably declaring all fields as IntPtr (except UINT DirtyRectsCount), then use var handle = GCHandle.Alloc(ObjectArray[0], GCHandleType.Pinned); (where ObjectArray is your array of structs) and assign DirtyRects = handle.AddrOfPinnedObject();. Of course, handle.Free(); after. Commented Jul 7, 2019 at 0:18
  • 2
    Since the size of these arrays is variable (plus the pointer can also be NULL), you must declare them as IntPtr and do the work yourself (using functions in the Marshal class). It's not a "custom marshaler" strictly speaking, but you'll have to do the work manually, yes. Commented Jul 7, 2019 at 6:49

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.