locked
VB Marshal size problem RRS feed

  • Question

  • Hi!

    I become back the error that the size of my Array is to big...

    How can i fit it?

    Here is the Array with the Problem:

        <StructLayout(LayoutKind.Sequential)> Public Structure VBSATZFREITEXTSUCHE
    
            ' *******************************************************************************************************
            ' Such Tabelle (max. 100 Spalten)
            <MarshalAs(UnmanagedType.ByValArray, SizeConst:=100)> Public SuchArray() As WPFStandardSuchTabelle
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=10)> Public SuchAnzahl As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=81)> Public SuchHinweis As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=10)> Public SuchNummer1 As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=257)> Public SuchKopf1 As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=257)> Public SuchKopf2 As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=257)> Public SuchKopf3 As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=257)> Public SuchKopf4 As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=257)> Public SuchKopf5 As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=257)> Public SuchKopf6 As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=257)> Public SuchKopf7 As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=257)> Public SuchKopf8 As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=257)> Public SuchKopf9 As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=257)> Public SuchKopf10 As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=257)> Public SuchKopf11 As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=257)> Public SuchKopf12 As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=257)> Public SuchKopf13 As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=257)> Public SuchKopf14 As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=257)> Public SuchKopf15 As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=257)> Public SuchKopf16 As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=257)> Public SuchKopf17 As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=257)> Public SuchDatei As String
    
            ' *******************************************************************************************************
    
        End Structure
    
    
        ' *******************************************************************************************************
        ' Such-Tabelle mit Feldlänge
        <StructLayout(LayoutKind.Sequential)> Public Structure WPFStandardSuchTabelle
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=101)> Public SuchWas As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=11)> Public SuchAufDatum As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=2)> Public SuchFehlerKZ As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=257)> Public SuchBeschreibung As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=257)> Public SuchImage As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=27)> Public SuchMitarbeiter As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=11)> Public SuchErledigenBisDatum As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=2)> Public SuchErledigtKZ As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=11)> Public SuchErledigtDatum As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=257)> Public SuchWasGemacht As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=31)> Public SuchText9 As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=31)> Public SuchText10 As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=31)> Public SuchText11 As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=31)> Public SuchText12 As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=31)> Public SuchText13 As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=31)> Public SuchText14 As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=31)> Public SuchText15 As String
        End Structure

    Now the Call...

        Declare Function QSLISTECALL Lib "QSLISTE.dll" (ByRef VBSATZ1 As VBSATZ01, ByRef VBSATZ4 As VBSATZFREITEXTSUCHE) As Integer
               CblStatus = QSLISTECALL(VBSATZ001, VBSATZFreitextSuche)
    

    Have anyone an idea without cutting fields?

    Best Regards

    Bernd

    Wednesday, June 25, 2014 1:54 PM

Answers

  • You did not answer my question. Did you try to manually marshal the data by using Marshal.PtrToStructure or not? Did it work or not?

    As far as I know it should work. The following example shows that Marshal.PtrToStructure supports objects larger than 64k.

    using System;
    using System.Diagnostics;
    using System.Runtime.InteropServices;
    
    [StructLayout(LayoutKind.Sequential)]
    struct Foo {
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
        public string text;
    }
    
    [StructLayout(LayoutKind.Sequential)]
    class Bar {
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10000)]
        public Foo[] foos;
    }
    
    class Program {
        static void Main() {
            IntPtr ptr;
    
            {
                var s = new Bar {
                    foos = new Foo[10000]
                };
    
                for (int i = 0; i < s.foos.Length; i++)
                    s.foos[i].text = i.ToString();
    
                Console.WriteLine(Marshal.SizeOf(s));
    
                ptr = Marshal.AllocCoTaskMem(Marshal.SizeOf(s));
    
                Marshal.StructureToPtr(s, ptr, false);
            }
    
            {
                var d = Marshal.PtrToStructure<Bar>(ptr);
    
                for (int i = 0; i < d.foos.Length; i++)
                    Debug.Assert(d.foos[i].text == i.ToString());
            }
        }
    }
    

    • Marked as answer by Bernd Riemke Sunday, July 2, 2017 5:48 PM
    Thursday, July 31, 2014 3:02 PM

All replies

  • Hi Bernd,

    I did some researches about this issue, I would suggest you add "SafeArraySubType:=VT_BSTR" attribute. For more information, please visit: http://msdn.microsoft.com/en-us/library/z6cfh6e6.aspx?cs-save-lang=1&cs-lang=vb#code-snippet-2

    If it still doesn't work. Please try to use a class instead of Structure, and use StringBuilder instead the String.

    If I misunderstood or my points are incorrect, please feel free to let me know.

    Have a nice time!

    Sincerely,


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Thursday, June 26, 2014 2:27 AM
  • Hi!

    I Vahe Problem with your hint...

     <MarshalAs(UnmanagedType.SafeArray, SafeArraySubType:=VT_BSTR)> Public SuchArray() As WPFStandardSuchTabelle

    I Change it to "SafeArray" but the Compiler say that he missing "VT_BSTR" declaration???

    Best Regards

    Bernd

    Thursday, June 26, 2014 6:50 AM
  • The VT_BSTR is a number: 8

    http://msdn.microsoft.com/en-us/library/windows/desktop/ms221170(v=vs.85).aspx

    Jimmy has suggested class rather than struct because structs are value types whilst classes are reference types.

    They go in different memory areas - stack and heap.

    Thursday, June 26, 2014 8:08 AM
  • This will not working...

    here is the error (SafeArrayTypeMismatchException):

     here is the actual code:

        <StructLayout(LayoutKind.Sequential)> Public Structure VBSATZFREITEXTSUCHE
    
            ' *******************************************************************************************************
            ' I NEDD > 100 Lines in an Array !!!
            <MarshalAs(UnmanagedType.SafeArray, SafeArraySubType:=8)> Public SuchArray() As WPFStandardSuchTabelle
            '  <MarshalAs(UnmanagedType.ByValArray, SizeConst:=100)> Public SuchArray() As WPFStandardSuchTabelle
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=10)> Public SuchAnzahl As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=81)> Public SuchHinweis As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=10)> Public SuchNummer1 As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=257)> Public SuchKopf1 As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=257)> Public SuchKopf2 As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=257)> Public SuchKopf3 As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=257)> Public SuchKopf4 As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=257)> Public SuchKopf5 As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=257)> Public SuchKopf6 As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=257)> Public SuchKopf7 As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=257)> Public SuchKopf8 As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=257)> Public SuchKopf9 As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=257)> Public SuchKopf10 As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=257)> Public SuchKopf11 As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=257)> Public SuchKopf12 As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=257)> Public SuchKopf13 As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=257)> Public SuchKopf14 As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=257)> Public SuchKopf15 As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=257)> Public SuchKopf16 As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=257)> Public SuchKopf17 As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=257)> Public SuchDatei As String
    
            ' *******************************************************************************************************
    
        End Structure
    
    
        ' *******************************************************************************************************
        ' Such-Tabelle mit Feldlänge
        <StructLayout(LayoutKind.Sequential)> Public Structure WPFStandardSuchTabelle
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=101)> Public SuchWas As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=11)> Public SuchAufDatum As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=2)> Public SuchFehlerKZ As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=257)> Public SuchBeschreibung As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=257)> Public SuchImage As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=27)> Public SuchMitarbeiter As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=11)> Public SuchErledigenBisDatum As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=2)> Public SuchErledigtKZ As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=11)> Public SuchErledigtDatum As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=257)> Public SuchWasGemacht As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=31)> Public SuchText9 As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=31)> Public SuchText10 As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=31)> Public SuchText11 As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=31)> Public SuchText12 As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=31)> Public SuchText13 As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=31)> Public SuchText14 As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=31)> Public SuchText15 As String
        End Structure

    Best Regards

    Bernd

    Thursday, June 26, 2014 8:37 AM
  • Hi Bernd,

    I created a VB.NET project to test your code. It works fine on my side. I did some researches about this issue. I am afraid that this issue occurred at where you use this structure. Please refer to: http://www.codeproject.com/Questions/295886/Received-SafeArrayTypeMismatchException-when-passi

    If I misunderstood or my points are incorrect, please feel free to let me know.

    Have a nice time!

    Sincerely,


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Friday, June 27, 2014 5:29 AM
  • Can you send me th1 code with my Details...

    You say you have test it with my Code...

    Best Regards

    Bernd

    Friday, June 27, 2014 6:36 AM
  • Friday, June 27, 2014 7:08 AM
  • Here you have a LINK where you can download the code...

    http://www.riemke-it.de/Beispiele/Tools/QSListe.zip

    Best Regards

    Bernd

    Friday, June 27, 2014 10:21 AM
  • Have anyone an Idea?

    Best Regards

    Bernd

    Saturday, June 28, 2014 2:19 PM
  • I'm on a windows 8.1 64 bit machine with 8 gig of ram.

    I spun it up - f5.

    It ran.

    What reproduces the issue for you?

    PS

    I was kind of expecting huge memory use but it goes from 2 gig to like 2.3gig which isn't really quite as exciting as I was expecting.

    I suggest you check your memory use out on your machine.

    • Edited by Andy ONeill Saturday, June 28, 2014 3:45 PM
    Saturday, June 28, 2014 3:40 PM
  • Debug the code then you can see the Problem on:

            Try
                CblStatus = QSLISTECALL(VBSATZ001, VBSATZFreitextSuche)
    
            Catch ex As Exception
    
            End Try
    

    You can see that you ar going to "Catch"....

    Best Regards

    Bernd

    Saturday, June 28, 2014 3:57 PM
  • I'm not great at VB, I do c# but I changed the code:

            Try
                CblStatus = QSLISTECALL(VBSATZ001, VBSATZFreitextSuche)
    
            Catch ex As Exception
                MsgBox("Broken" & vbCrLf & ex.Message)
    
            End Try

    And put a break point on that msgbox.

    There was no exception.

    Saturday, June 28, 2014 4:09 PM
  • Hi!

    I made a Little Change so you can see my Problem better!

    http://www.riemke-it.de/Beispiele/Tools/QSListe.zip

    I blow up the Array to 999 times...

    Please load the sample again down then you can see the bug better!

    Best Regards

    Bernd

    Sunday, June 29, 2014 10:56 AM
  • Have you seen the Problem?

    Best Regards

    Bernd

    Monday, June 30, 2014 7:59 AM
  • I reproduced the problem with your modified code.

    Unfortunately, I don't have much useful input.

    On my computer a simple "fix" would be not to use more than one of those structs at a time.Only run it on a 64bit  machine with more than 2 gig of ram and you'll be fine.

    If that's no good to you and refactoring to use a class is no good to you then I've got nothing.

    Monday, June 30, 2014 9:11 AM
  • My Machine have 24gig ram! --> It is more then the most have...

    I have a Windos 7 64 bit machine...

    There are 2 structure in the sample (the first are fields and the second is the Array with the Problem...)

    And ther is comming the error!...

    I Think that is a 64K Limit for this structure!?

    Now the Array is 999

    I can bring it down to 100... The error is the same... (If that help you)!?

    Best Regards

    Bernd

    Monday, June 30, 2014 9:40 AM
  • Your machine is power than mine! :) How about Modify the structure to class, and string to StringBuilder.
    Tuesday, July 1, 2014 5:49 AM
  • If it works!?

    Have you an idea how?

    I Need a FIX LENGHT in an Array! Not variable... e.g. 999 or 100 or 500....

    This is important....

    Can you make it for me or have you an sample where i can see how it work?

    It must be marshaling because it is an non .Net DLL...

    Best Regards

    Bernd

    Tuesday, July 1, 2014 6:23 AM
  • No idea anyone?

    Best regards

    Bernd

    Thursday, July 3, 2014 6:41 AM
  • "I Think that is a 64K Limit for this structure!?"

    Yes, PInvoke imposes a limit on marshaled structs. Try marshaling it manually, AFAIR the restriction applies only to marshaling done during a PInvoke call and not to marshaling in general. 

    Change the method parameter to an IntPtr and use Marshal.StructureToPtr & co. The MSDN documentation page has an example on how to use StructureToPtr, you just need to replace the call to PtrToStructure with a call to your dll export method.

    Thursday, July 3, 2014 7:02 AM
  • I think that i was not the first People that have the Problem with Marshal...!?

    The documentation can not help me because i habe Arrays...

    I Need a better idea for this probelm...

    Or a good sample where i can see how it works...

    Best Regards

    Bernd

    Thursday, July 3, 2014 8:11 AM
  • The arrays are inside the structure, as far as I can tell you aren't passing an array of those structures to the QSLISTECALL function. Anyway, I realized that what you need is actually PtrToStructure because you want to get data back from that method. Here's an example:

    Dim ptr As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(VBSATZFreitextSuche))
    
    Try
        CblStatus = QSLISTECALL(VBSATZ001, VBSATZ002, VBSATZ003, ptr)
        Marshal.PtrToStructure(ptr, VBSATZFreitextSuche)
    Catch ex As Exception
        MsgBox("Broken" & vbCrLf & ex.Message)
    Finally
        Marshal.FreeHGlobal(ptr)
    End Try
    

    And the QSLISTECALL needs to use an IntPtr for the last parameter:

    Declare Function QSLISTECALL Lib "QSLISTE.dll" (ByRef VBSATZ1 As VBSATZ01, ByRef VBSATZ2 As VBVorlagen, ByRef VBSATZ3 As VBMitarbeiter, ByVal VBSATZ4 As IntPtr) As Integer

    And VBSATZFREITEXTSUCHE needs to be a class and not a struct.

    That said, your program works with an array length of 50. If you change the length to 100 that means you'll also need to modify that dll. Does that mean that you have control over that dll? Maybe you can do things differently somehow, marshalling such large structures is not very efficient.

    Thursday, July 3, 2014 9:56 AM
  • I will test it...

    Please wait...

    It Need a little bit...

    Thursday, July 3, 2014 10:12 AM
  • Hi!

    I have a Problem with the "IntPtr"...

    Is this an object?

    Have you any mor Information for me?

    Or can i use any other way?

    Best Regards

    Bernd

    Tuesday, July 8, 2014 8:43 AM
  • Yes i have control to the dll that will read the Array...

    Best Regards

    Bernd

    Tuesday, July 8, 2014 8:44 AM
  • What problem are you having? IntPtr is a structure: http://msdn.microsoft.com/en-us/library/system.intptr(v=vs.110).aspx
    Tuesday, July 8, 2014 8:45 AM
  • Have you an example eg. Windows API call?

    Where i can see how the structure is working?

    Tuesday, July 8, 2014 8:48 AM
  • For more Background...

    I work with three differetn progamming language on this Project...

    And the extern dll is a non .Net dll

    Tuesday, July 8, 2014 8:50 AM
  • Is there any other way witouth "IntPtr" because the arry comse wrong in the extern .dll

    Best Regards

    Bernd

    Tuesday, July 8, 2014 9:27 AM
  • "Have you an example eg. Windows API call? Where i can see how the structure is working?"

    IntPtr is the equivalent of a native pointer, it can be used anywhere a native function expects a pointer. Normally you pass a reference or a ref to a value type and the PInvoke marshaler takes care of allocating native memory, copying the necessary data to native memory and then passing the pointer to the native memory to the native function. Problem is, the PInvoke marshaler limits the object size to 64kbytes. My example is trying to get around this limitation by manually marshaling that large structure.

    Here's an example of calling Win32's GetSystemTime function:

    using System;
    using System.Runtime.InteropServices;
    
    class Program {
        [StructLayout(LayoutKind.Sequential)]
        class SYSTEMTIME {
            public ushort wYear;
            public ushort wMonth;
            public ushort wDayOfWeek;
            public ushort wDay;
            public ushort wHour;
            public ushort wMinute;
            public ushort wSecond;
            public ushort wMilliseconds;
        }
    
        [DllImport("kernel32.dll")]
        private static extern void GetSystemTime(IntPtr pSystemTime);
    
        static void Main() {
            SYSTEMTIME time = new SYSTEMTIME();
    
            IntPtr pSystemTime = Marshal.AllocHGlobal(Marshal.SizeOf(time));
    
            try {
                GetSystemTime(pSystemTime);
                Marshal.PtrToStructure(pSystemTime, time);
            }
            finally {
                Marshal.FreeHGlobal(pSystemTime);
            }
    
            Console.WriteLine(time.wYear);
        }
    }
    

    It's very similar to your case and works fine in my tests.

    "Is there any other way witouth "IntPtr" because the arry comse wrong in the extern .dll"

    The best thing to do is to make that structure smaller. That ByValArray shouldn't be ByVal, it should be a normal array. I don't know what constraints you have on the .dll side to tell if this is possible or not.

    • Marked as answer by Yang,Chenfei Wednesday, July 30, 2014 7:21 AM
    • Unmarked as answer by Bernd Riemke Wednesday, July 30, 2014 7:24 AM
    Tuesday, July 8, 2014 9:53 AM
  • The Probleme with the structure is that i have an Array that have a fix size from eg. 100257 and the normal Marshal can only a size of 64000...

    I can not split the Array :-(

    Have anyone an idea?

    Best Regards

    Bernd

    Wednesday, July 30, 2014 7:26 AM
  • My understanding is the whole idea here is to take data from a cobol programme and use it in c#.  Or maybe vice versa.

    I would consider decoupling them using a message queue.

    RabbitMQ or MSMQ maybe

    You can then write a bunch of messages rather than try and pass a HUGE great structure across.


    • Edited by Andy ONeill Wednesday, July 30, 2014 9:34 AM
    Wednesday, July 30, 2014 9:33 AM
  • This is too many work for a Cobol programmer and it is to slow...

    The way via Marshal is very easy and faster!

    The own Problem is the 64KB Wall...

    I think that i not the first programmer with this Problem!

    The Problem is not a Problem from Cobol or any other programer language...

    It is a Problem from Marshaling...

    Best Regards

    Bernd

    Wednesday, July 30, 2014 10:03 AM
  • It's not clear to me what you tried and what did not work. Did you try my suggestion of marshaling manually? That's supposed to work with structures larger than 64Kbytes.

    Other than that there's little you can do on the .NET side. Not knowing a thing about COBOL there's little I can suggest here but it's clear that something has to change in your approach of the problem.

    Thursday, July 31, 2014 11:52 AM
  • The Problem ist the size of the structure! --> 64K Limit...

    If the strucruree is bigger then the Framework give me a Feedback that the structure ist to big :-(

    E.G. in Cobol there is no site Limit... (this ist NOT a Cobol Problem!)

    The Problem is a General Problem with a 64k size (see the structure at begin...)

    Best Regards

    Bernd

    Thursday, July 31, 2014 2:45 PM
  • You did not answer my question. Did you try to manually marshal the data by using Marshal.PtrToStructure or not? Did it work or not?

    As far as I know it should work. The following example shows that Marshal.PtrToStructure supports objects larger than 64k.

    using System;
    using System.Diagnostics;
    using System.Runtime.InteropServices;
    
    [StructLayout(LayoutKind.Sequential)]
    struct Foo {
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
        public string text;
    }
    
    [StructLayout(LayoutKind.Sequential)]
    class Bar {
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10000)]
        public Foo[] foos;
    }
    
    class Program {
        static void Main() {
            IntPtr ptr;
    
            {
                var s = new Bar {
                    foos = new Foo[10000]
                };
    
                for (int i = 0; i < s.foos.Length; i++)
                    s.foos[i].text = i.ToString();
    
                Console.WriteLine(Marshal.SizeOf(s));
    
                ptr = Marshal.AllocCoTaskMem(Marshal.SizeOf(s));
    
                Marshal.StructureToPtr(s, ptr, false);
            }
    
            {
                var d = Marshal.PtrToStructure<Bar>(ptr);
    
                for (int i = 0; i < d.foos.Length; i++)
                    Debug.Assert(d.foos[i].text == i.ToString());
            }
        }
    }
    

    • Marked as answer by Bernd Riemke Sunday, July 2, 2017 5:48 PM
    Thursday, July 31, 2014 3:02 PM