Microsoft Developer Network > Forums Home > Smart Device Development Forums > .NET Compact Framework > Code that works on .NET Framework but not on the .NET Compact Framework

Answered Code that works on .NET Framework but not on the .NET Compact Framework

  • Wednesday, February 28, 2007 8:10 PM
     
     

    Hi all!

    The following C# code:


    [StructLayout(LayoutKind.Sequential)]
    internal class ASRX_RO_Name_And_Rule
    {
         public byte[] Name;
         public IntPtr Rule;
    }

    private void button1_Click(object sender, EventArgs e)
    {
         ASRX_RO_Name_And_Rule[] roNameAndRule = new ASRX_RO_Name_And_Rule[1];
         roNameAndRule[0] = new ASRX_RO_Name_And_Rule();
         roNameAndRule[0].Name = String2ASCII("Test");
         roNameAndRule[0].Rule = IntPtr.Zero;

         IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(roNameAndRule[0]));
         Marshal.StructureToPtr(roNameAndRule[0], ptr, false);
    }

    internal byte[] String2ASCII(string text)
    {
         return Encoding.ASCII.GetBytes(text + '\0');
    }

    Correctly works in a Windows Form application, but the Marshal.AllocHGlobal instruction causes a NotSupportedException if I execute it in a Smart Device project. I need this code because I must copy into memory a struct to be passed to a C++ function via Platform Invoke.

    Can anyone help me?

    Thanks in advance.

Answers

  • Thursday, March 01, 2007 6:16 PM
     
     Answered

    I'll leave for Microsoft guys to comment on why it's doing that. As for workaround, you can get the size of the structure youself. Something like that:

    int size = String2ASCII("Test").Length + 4;


     

All Replies

  • Wednesday, February 28, 2007 10:36 PM
     
     
    It's not the Marshal.AllocHGlobal it's the Marshal.SizeOf that is throwing this exception. It probably doesn't like the byte[] Name
  • Wednesday, February 28, 2007 10:51 PM
     
     

    Hi!

    Thank you for the replay... But why Marshal.SizeOf throws an exception only in the .NET Compact Framework? And how I can solve this problem?

  • Thursday, March 01, 2007 6:16 PM
     
     Answered

    I'll leave for Microsoft guys to comment on why it's doing that. As for workaround, you can get the size of the structure youself. Something like that:

    int size = String2ASCII("Test").Length + 4;


     

  • Thursday, March 22, 2007 2:18 AM
     
     

    Hi Marco - did you get a solution to this?  I have the same issue.

     

    Thanks, Rob

  • Friday, August 24, 2007 6:30 PM
     
     
    I would be very interested in a solution aswell. I am trying to marshal structures in the following code and each time I call Marshal it throws an exception System.NotSupportedException.

             WSAData wsaData = new WSAData();
             IntPtr wsaDataPtr = LocalAlloc(0, Marshal.SizeOf(typeof(WSAData)));

    with

            [StructLayout(LayoutKind.Sequential)]
            public class WSAData
            {
                public Int16 wVersion = 0;
                public Int16 wHighVersion = 0;
                public char[] szDescription = new char[257];
                public char[] szSystemStatus = new char[127];
                public Int16 iMaxSockets = 0;
                public Int16 iMaxUdpDg = 0;
                public IntPtr lpVendorInfo = IntPtr.Zero;
            }
            [StructLayout(LayoutKind.Sequential)]
            internal class WSAQUERYSET
            {
                public Int32 dwSize = 0;
                public String szServiceInstanceName = null;
                public IntPtr lpServiceClassId = IntPtr.Zero;
                public IntPtr lpVersion = IntPtr.Zero;
                public String lpszComment = null;
                public Int32 dwNameSpace = 0;
                public IntPtr lpNSProviderId = IntPtr.Zero;
                public String lpszContext = null;
                public Int32 dwNumberOfProtocols = 0;
                public IntPtr lpafpProtocols = IntPtr.Zero;
                public String lpszQueryString = null;
                public Int32 dwNumberOfCsAddrs = 0;
                public IntPtr lpcsaBuffer = IntPtr.Zero;
                public Int32 dwOutputFlags = 0;
                public IntPtr Blob = IntPtr.Zero;
            }
  • Tuesday, February 05, 2008 9:43 AM
     
     
    i've got the same problem in Marshal Class (SizeOf, PtrToStructure, StructureToPtr), doesn't work on CF.
    App: WM5
    CF: 2.0
    Device : HP iPAQ hx2495c

    does any body got solution?


    thank you
  • Tuesday, February 05, 2008 7:02 PM
    Moderator
     
     

    You can only do that with blittable structures. That means structure (after marshaling) must occupy single continuous memory region. That is only possible if structure contains:

    -          Primitive types like Int32.

    -     Blittable nested structures.

    -          Nested strings of fixed length (must be decorated with respective attribute).

    -          Nested fixed length arrays of primitive types.

    Nothing else is allowed. Here’s an example of such a structure with correct attributes:

    Code Snippet

    [StructLayout(LayoutKind.Sequential)]

    public struct Blittable

    {

      Nested nested; // Blitable nested structure is OK.

     

      Int32 integer; // Primitive type OK

     

      IntPtr pointer; // Pointer is OK

     

      [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]

      String text; // Nested fixed length string is OK.

     

      [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]

      Byte[] bytes; // Nesed fixed size array of prmitive types is OK

    }

     

    [StructLayout(LayoutKind.Sequential)]

    public struct Nested

    {

      Int32 integer; // Primitive type OK

      IntPtr pointer; // Pointer is OK

    }

     

     

    If you need to marshal any reference types (e.g. pointers to strings) in the structure then you would have to declare them as IntPtr’s and take care if marshaling manually.

  • Wednesday, February 06, 2008 8:16 AM
     
     
    The code is this :

     Public Delegate Function Prn2CallBack(ByVal hwnd As IntPtr, _
          ByVal msg As Integer, ByVal wp As Integer, ByVal lp As Integer) As Integer
    '----------------------------
    Declare Function LocalFree Lib "coredll" (ByVal hMem As IntPtr) As IntPtr
    '-----------------------------
        <StructLayout(LayoutKind.Sequential)> _
        Public Class PageSetupDlgTag
            Public lStructSize As Integer = 0
            Public hwndOwner As IntPtr = IntPtr.Zero
            Public hDevMode As IntPtr = IntPtr.Zero
            Public hDevNames As IntPtr = IntPtr.Zero
            Public Flags As Integer = 0
            Public rtMinMargin As Rectangle
            Public rtMargin As Rectangle
            Public hInstance As IntPtr = IntPtr.Zero
            Public lCustData As Integer = 0
            Public lpfnPageSetupHook As Prn2CallBack       
            Public lpPageSetupTemplateName As String = Nothing
            Public hPageSetupTemplate As IntPtr = IntPtr.Zero
        End Class ' PageSetupDlgTag
    '-----------------------------
        Public Const PSD_DISABLEMARGINS As Integer = &H10
        Public Const PSD_INHUNDREDTHSOFMILLIMETERS As Integer = &H8
        Public Const PSD_MARGINS As Integer = &H2
        Public Const PSD_MINMARGINS As Integer = &H1
        Public Const PSD_DISABLEPRINTRANGE As Integer = &H10000000
    '----------------------------
        Public Function SetDefaultPrinter() As Boolean

            Dim PageSetup As New PageSetupDlgTag

    PageSetup.lStructSize = Marshal.SizeOf(PageSetup) -> ERROR : Run-time exception thrown : System.NotSupportedException - NotSupportedException    - occurred in mscorlib.dll

    PageSetup.Flags = PSD_DISABLEMARGINS + PSD_INHUNDREDTHSOFMILLIMETERS + PSD_MARGINS + PSD_MINMARGINS + PSD_DISABLEPRINTRANGE

            Dim bfr As GCHandle = GCHandle.Alloc(PageSetup, GCHandleType.Pinned)
            Dim ptr As IntPtr = bfr.AddrOfPinnedObject

            SetDefaultPrinter = PageSetupDlg(ptr) <> 0

            Marshal.PtrToStructure(ptr, PageSetup) -> ERROR : Run-time exception thrown : System.NotSupportedException - NotSupportedException - occurred in mscorlib.dll

            bfr.Free()

            LocalFree(PageSetup.hDevMode)
            LocalFree(PageSetup.hDevNames)

        End Function

    info :
    - WM5 .Net CF 2 sp2
    - HP hx2495c
    - Connected to PP55 PDA Printer

    => is the code wrong? is there any way to solve it or may be tricky solution that should not use Marshal Class but others class - maybe?

    really need your guide

    Thank You
  • Wednesday, February 06, 2008 6:20 PM
    Moderator
     
     

    Each member of the structure MUST meet criterias I've outlined before. Since you’re getting an exception one or more members do not. So go through all members of your structure and fix these not meeting criteria.

     

    Note: blittable nested structures are OK as well.

    One more thing: Rectangle structure on the managed side might not be the same as Rectangle structure on the native side. I would suggest declaring all equivalents to native structures in your code.