Locked Marshal Problems with ByValArray

  • Monday, March 26, 2012 2:40 PM
     
      Has Code

    Hi!

    i have an array that not will working...

    Here is the structure:

       <StructLayout(LayoutKind.Sequential)> Public Structure MySatz
            <MarshalAs(UnmanagedType.ByValArray, SizeConst:=25)> Public MyArrayGrKo() As MYKopfTabelle
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=10)> Public MyKopfAnzahl As String
             <MarshalAs(UnmanagedType.ByValArray, SizeConst:=25)> Public MyArrayGrZeilen() As MYGridZeilen
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=51)> Public MyZeilenAnzahl As String
        End Structure
        <StructLayout(LayoutKind.Sequential)> Public Structure MYGridZeilen
            <MarshalAs(UnmanagedType.ByValArray, SizeConst:=999)> Public MyArray2() As MYZeilen
        End Structure
        <StructLayout(LayoutKind.Sequential)> Public Structure MYZeilen
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=81)> Public TABGridElement As String
        End Structure

    If i male a call wit this Array i becom a .Net Error that the structure is not suportet!?

    Is the array to big?

    How big can be say the array?

    Or is ther a Bug in my Code?

    With a smaler Array will it working!?

    Have anyone an Idea?

    Best Regards

    Bernd

All Replies

  • Monday, March 26, 2012 7:52 PM
     
      Has Code

    Does the error message also say why the structure is not supported?

    What's the declaration of MYKopfTabelle?

    The type of the array which you pass is MySatz()?

    What's the declaration of the function to which you pass the array? (although I won't be able to test it)

    For testing, if I declare the missing type simply as

       Structure MYKopfTabelle
          Public i As Integer
       End Structure

    retrieving the size does not fail

          Dim size = Marshal.SizeOf(GetType(MySatz))

    so I think passing it shouldn't fail either.


    Armin


  • Tuesday, March 27, 2012 8:30 AM
     
      Has Code

    here is the complete structure:

        <StructLayout(LayoutKind.Sequential)> Public Structure AVW13SATZ
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=31)> Public AVWSTFUNKTION As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=11)> Public AVWSTASTE As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=2)> Public AVWSTASTEOK As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=31)> Public AVWSBUTTON As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=51)> Public AVWSZIELFELD As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=31)> Public AVWSHGFarbe As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=31)> Public AVWSVGFarbe As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=31)> Public AVWSORTIERUNG As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=11)> Public AVWSANZAHL As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=1001)> Public AVWSAUSWAHL As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=80)> Public AVWSTEF00STZ1A As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=11)> Public AVWSTEF00STZ2A As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=6)> Public AVWSTEF00STZ3A As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=2)> Public AVWSTEF00STZ4A As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=2)> Public AVWSTEF00STZ5A As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=11)> Public AVWSTEF00STZ6A As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=6)> Public AVWSTEF00STZ7A As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=11)> Public AVWSTEF00STZ8A As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=11)> Public AVWSTEF00STZ9A As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=4)> Public AVWSTEF00STZ10A As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=4)> Public AVWSTEF00STZ11A As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=9)> Public AVWSTEF00STZ12A As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=101)> Public AVWSTEF00STZ13A As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=4)> Public AVWSTEF00STZ14A As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=4)> Public AVWSTEF00STZ15A As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=4)> Public AVWSTEF00STZ16A As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=6)> Public AVWSTEF00STZ17A As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=11)> Public AVWSTEF00STZ18A As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=10)> Public AVWSTEF00STZ19A As String
            <MarshalAs(UnmanagedType.ByValArray, SizeConst:=99)> Public MyArraySB() As MYSBTabelle
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=10)> Public MySBAnzahl As String
            <MarshalAs(UnmanagedType.ByValArray, SizeConst:=99)> Public MyArrayTA() As MYTATabelle
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=10)> Public MyTAAnzahl As String
            <MarshalAs(UnmanagedType.ByValArray, SizeConst:=99)> Public MyArrayERF() As MYERFTabelle
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=10)> Public MyERFAnzahl As String
            <MarshalAs(UnmanagedType.ByValArray, SizeConst:=25)> Public MyArrayGrKo() As MYKopfTabelle
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=10)> Public MyKopfAnzahl As String
            <MarshalAs(UnmanagedType.ByValArray, SizeConst:=99)> Public MyArrayGrZe() As MYGridTabelle
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=10)> Public MyTabAnzahl As String
        End Structure
        <StructLayout(LayoutKind.Sequential)> Public Structure MYSBTabelle
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=4)> Public TABSB As String
        End Structure
        <StructLayout(LayoutKind.Sequential)> Public Structure MYTATabelle
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=4)> Public TABTA As String
        End Structure
        <StructLayout(LayoutKind.Sequential)> Public Structure MYERFTabelle
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=9)> Public TABERF As String
        End Structure
        <StructLayout(LayoutKind.Sequential)> Public Structure MYKopfTabelle
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=81)> Public TABGridKopf As String
        End Structure
        <StructLayout(LayoutKind.Sequential)> Public Structure MYGridTabelle
            ' Maximal 25 Spalten
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=2)> Public TABGridX As String
            <MarshalAs(UnmanagedType.ByValArray, SizeConst:=25)> Public TabGridZeile() As MYGridTabelleSpalte
        End Structure
        <StructLayout(LayoutKind.Sequential)> Public Structure MYGridTabelleSpalte
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=81)> Public TABGridZeileSpalte As String
        End Structure

    and here is the call that will not working:

            Dim CblStatus As Integer
            Dim AVW13SATZ001 = New AVW13SATZ
            AVW13SATZ001.AVWSTFUNKTION = "USETABLE"
            CblStatus = AVW13CALL(AVW13SATZ001)

    The size of the comlpete structure is 2028236 characters

    How can i say that the structure is so big?

    Best Regards

    Bernd

  • Tuesday, March 27, 2012 10:28 AM
     
      Has Code

    Does the error message also say why the structure is not supported?

    What's the declaration of the AVW13CALL? Maybe you want to pass the record ByVal instead of ByRef?

    The size I get from Marshal.SizeOf(GetType(AVW13SATZ)) is 205,959, not 2,028,236

    I don't see a reason why it doesn't work. There shouldn't be a size limit (probably not before 2^31). The marshaller is also able to report the offset of each item correctly:

          Dim satz As AVW13SATZ
          Dim t = satz.GetType
          Dim infos = t.GetFields(Reflection.BindingFlags.Public Or Reflection.BindingFlags.Instance)
    
          For Each info In infos
             Dim offset = Marshal.OffsetOf(t, info.Name)
             Debug.Print("{0,10}: {1}", offset, info.Name)
          Next
    
    So, I'm afraid, I don't see what's going wrong. Maybe the exception shows more details?


    Armin

  • Tuesday, March 27, 2012 11:18 AM
     
     
  • Tuesday, March 27, 2012 1:59 PM
     
     

    I was asking you twice what's the exact exception message. You were guessing the structure might be too big, but you should have clearly stated that this was not your own guessing. If you had straight posted the exception message, it would have simplified it without keeping me guessing if there is a limit for the marshaller. The exception message is:

    System.Runtime.InteropServices.MarshalDirectiveException wurde nicht behandelt.
      Message=""parameter #1" kann nicht gemarshallt werden: Interne Einschränkung: Die Struktur ist zu komplex oder zu groß.."

    Translated:

    System.Runtime.InteropServices.MarshalDirectiveException has not been handled.
      Message=""parameter #1" can not be marshalled: Internal limitation: The structure is too complex or too big."

    Now I'm only unable to add anything to what the message already says.

    Search for MarshalDirectiveException and possible workarounds (globalloc, copy, pass pointer)


    Armin

  • Tuesday, March 27, 2012 2:23 PM
     
     

    The Error is not easy to handle because there is not help about the error...

    Whats about the "Internal limitation"??

    What are the limitation?

  • Tuesday, March 27, 2012 6:36 PM
     
     Answered

    According to the web search results, there might be a 64K limit. I do not know why. Use the other approach mentioned: Marshal.AllocHGlobal, Marshal.StructureToPtr. However, I don't know if StructureToPtr can handle it. If not, you must write data piece by piece (also using the Marshal class), then pass the pointer to the allocated block to the API function.


    Armin