2

Right know in my code I have structure declared as like this, with fixed this 16, know at compile time.

struct CONSOLE_SCREEN_BUFFER_INFOEX
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
public int ColorTable[];
}

but what I need is to be able to have this structure:

struct CONSOLE_SCREEN_BUFFER_INFOEX
{
   int arraySize;
   [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0)]
   public int ColorTable[];
}

get the arraySize from C function response, initialize ColorTable array with proper size, put result of response into ColorTable.

Not sure if it's possible, just doing investigation right now, and any comments are very welcome.

6
  • It is not the proper way to declare that field, it should be done with [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public int[] ColorTable. Which gives you more rope, but not enough to make it depend on the Size field. You'll need to write a custom marshaller. Commented Aug 28, 2013 at 14:49
  • Hey Hans, you are right, this is exactly how I am doing it right now: [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)], I just made it similar to Jon's code to avoid confusion. But now the request is to have it as [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0)] and then change size, when size is known, custom marshaller is exactly what I am interesting in, I just never touched this before, so need to know where to start Commented Aug 28, 2013 at 14:52
  • This question would be better with a bespoke example. All those extra fields are superfluous for the discussion. Hans is correct that there's no need for unsafe here. Jon presumably just picked on this as a way to illustrate fixed. But ByValArray is the right approach. You could use a custom marshaller. Or you could do it with IntPtr, Marshal.AllocHGlobal, Marshal.PtrToStructure and Marshal.Copy. Commented Aug 28, 2013 at 15:14
  • 1
    Your ultimate mistake is basing your question on a really bad example. Ask the proper one, show what you really need to interop with. Commented Aug 28, 2013 at 15:19
  • 1
    edited, my question for it to be more related to my real situation. Commented Aug 28, 2013 at 15:27

1 Answer 1

3

You can do this easily enough with some manual marshalling using the Marshal class. For example:

[DllImport(@"MyLib.dll")]
private static extern void Foo(IntPtr structPtr);

private static IntPtr StructPtrFromColorTable(int[] colorTable)
{
    int size = sizeof(int) + colorTable.Length*sizeof(int);
    IntPtr structPtr = Marshal.AllocHGlobal(size);
    Marshal.WriteInt32(structPtr, colorTable.Length);
    Marshal.Copy(colorTable, 0, structPtr + sizeof(int), colorTable.Length);
    return structPtr;
}

private static int[] ColorTableFromStructPtr(IntPtr structPtr)
{
    int len = Marshal.ReadInt32(structPtr);
    int[] result = new int[len];
    Marshal.Copy(structPtr + sizeof(int), result, 0, len);
    return result;
}

static void Main(string[] args)
{
    int[] colorTable = new int[] { 1, 2, 3 };
    IntPtr structPtr = StructPtrFromColorTable(colorTable);
    try
    {
        Foo(structPtr);
        colorTable = ColorTableFromStructPtr(structPtr);
    }
    finally
    {
        Marshal.FreeHGlobal(structPtr);
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

@Stanislav You might be interested in this question: stackoverflow.com/questions/18498452/…

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.