Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C#
  4. Passing a Class to an Unmanaged function as parameter

Passing a Class to an Unmanaged function as parameter

Scheduled Pinned Locked Moved C#
help
6 Posts 3 Posters 1 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • S Offline
    S Offline
    shajuMathew
    wrote on last edited by
    #1

    Hai all... I was trying to pass a class to an Unmanaged function. The class has a member of type, of the same class. Is it possible to pass a Managed class(Class having a member of it's own type) to an Unmanaged function. Thanks in advance:rose: Below is what i did... This is the class i created to pass into an Unmanaged function as parameter [StructLayout(LayoutKind.Explicit )] public class MyWindow { [FieldOffset (0)] public String className; [FieldOffset (16)] public String caption; [FieldOffset (32)] public MyWindow child ; } But if i remove the class member 'child' from the class it works well. Unmanaged function Decleration [DllImport("user32")] public static extern bool EnumChildWindows(int hwndParent, EnumChildDelegare lpEnumFunc, MyWindow lParam) ; This is the way how i call the unmanaged function MyWindow m = new MyWindow (); Win32Calls.EnumChildWindows (winHandle,w.enumChildDlgate ,m); And i am getting this error. An unhandled exception of type 'System.TypeLoadException' occurred in CSRecorder.exe Additional information: Can not marshal field child of type CSRecorder.MyWindow: This type can not be marshaled as a structure field. Shaju Mathew

    H U 2 Replies Last reply
    0
    • S shajuMathew

      Hai all... I was trying to pass a class to an Unmanaged function. The class has a member of type, of the same class. Is it possible to pass a Managed class(Class having a member of it's own type) to an Unmanaged function. Thanks in advance:rose: Below is what i did... This is the class i created to pass into an Unmanaged function as parameter [StructLayout(LayoutKind.Explicit )] public class MyWindow { [FieldOffset (0)] public String className; [FieldOffset (16)] public String caption; [FieldOffset (32)] public MyWindow child ; } But if i remove the class member 'child' from the class it works well. Unmanaged function Decleration [DllImport("user32")] public static extern bool EnumChildWindows(int hwndParent, EnumChildDelegare lpEnumFunc, MyWindow lParam) ; This is the way how i call the unmanaged function MyWindow m = new MyWindow (); Win32Calls.EnumChildWindows (winHandle,w.enumChildDlgate ,m); And i am getting this error. An unhandled exception of type 'System.TypeLoadException' occurred in CSRecorder.exe Additional information: Can not marshal field child of type CSRecorder.MyWindow: This type can not be marshaled as a structure field. Shaju Mathew

      H Offline
      H Offline
      Heath Stewart
      wrote on last edited by
      #2

      First, change the class to a struct. This allocates the data on the stack so it will not be moved. While this isn't the direct cause of your problem, it may lead to them. If it's a class - which is allocated on the heap - the GC (Garbage Collector) may move it when necessary and your handle that your enumerator is using would be invalid. Declaring this as a struct should also fix the other error. There is a problem with your EnumChildWindows as well. An HWND is a processor-dependent type. You should really declare this as IntPtr, which works well since P/Invoking other unmanaged Windows APIs will use IntPtr and Control.Handle (the HWND for the control) is also of type IntPtr. Any native int or unsigned int should be declared as an IntPtr. Also, for your struct, just use LayoutKind.Sequential. You really don't even need that, however, since the memory address to your struct's instance is being passed to your enumerator so it doesn't need to be marshaled for use with unmanaged code. Just a couple of tips.

      Microsoft MVP, Visual C# My Articles

      S 1 Reply Last reply
      0
      • S shajuMathew

        Hai all... I was trying to pass a class to an Unmanaged function. The class has a member of type, of the same class. Is it possible to pass a Managed class(Class having a member of it's own type) to an Unmanaged function. Thanks in advance:rose: Below is what i did... This is the class i created to pass into an Unmanaged function as parameter [StructLayout(LayoutKind.Explicit )] public class MyWindow { [FieldOffset (0)] public String className; [FieldOffset (16)] public String caption; [FieldOffset (32)] public MyWindow child ; } But if i remove the class member 'child' from the class it works well. Unmanaged function Decleration [DllImport("user32")] public static extern bool EnumChildWindows(int hwndParent, EnumChildDelegare lpEnumFunc, MyWindow lParam) ; This is the way how i call the unmanaged function MyWindow m = new MyWindow (); Win32Calls.EnumChildWindows (winHandle,w.enumChildDlgate ,m); And i am getting this error. An unhandled exception of type 'System.TypeLoadException' occurred in CSRecorder.exe Additional information: Can not marshal field child of type CSRecorder.MyWindow: This type can not be marshaled as a structure field. Shaju Mathew

        U Offline
        U Offline
        User 929285
        wrote on last edited by
        #3

        When I was marshalling EnumChildWindows, I declared the function like that: [DllImport("user32.dll",SetLastError=true)] public static extern bool EnumChildWindows( IntPtr hWndParent, User32Functions.EnumWindowsCallback lpEnumFunc, IntPtr lParam ); The point is, why do you need to pass a class or struct as the third parameter? I followed the MSDN recommendation and called the function like that: GCHandle gch=GCHandle.Alloc(this.twHandles); User32.EnumChildWindows(handleParent,this.enumThreadCallback,(IntPtr)gch); gch.Free(); Here this.twHandles is a text writer, which i later (in the callback function) use like so: private bool CaptureEnumThreadWindows(int handle, IntPtr param) { GCHandle gch=(GCHandle)param; TextWriter tw=(TextWriter)gch.Target; twHandles.Write(handle.ToString()+" "); twHandles.Flush(); return true; } Anyway, MSDN recommends to use GCHandle , 'so the delegate does not get moved by GC before the call ends, however I was trying to use without GCHandle, just passing IntPtr.Zero as the last parameter and it works anyway. Frankly I don't understand how this (GCHandle) can prevent the delegate from being moved by GC, but that's what MSDN says. (see GCHandle sample)

        S 1 Reply Last reply
        0
        • H Heath Stewart

          First, change the class to a struct. This allocates the data on the stack so it will not be moved. While this isn't the direct cause of your problem, it may lead to them. If it's a class - which is allocated on the heap - the GC (Garbage Collector) may move it when necessary and your handle that your enumerator is using would be invalid. Declaring this as a struct should also fix the other error. There is a problem with your EnumChildWindows as well. An HWND is a processor-dependent type. You should really declare this as IntPtr, which works well since P/Invoking other unmanaged Windows APIs will use IntPtr and Control.Handle (the HWND for the control) is also of type IntPtr. Any native int or unsigned int should be declared as an IntPtr. Also, for your struct, just use LayoutKind.Sequential. You really don't even need that, however, since the memory address to your struct's instance is being passed to your enumerator so it doesn't need to be marshaled for use with unmanaged code. Just a couple of tips.

          Microsoft MVP, Visual C# My Articles

          S Offline
          S Offline
          shajuMathew
          wrote on last edited by
          #4

          Thanks... Heath Stewart The tips helped .. But i cannot change class to struct. Since struct won't allow the same struct as a member Shaju Mathew

          H 1 Reply Last reply
          0
          • U User 929285

            When I was marshalling EnumChildWindows, I declared the function like that: [DllImport("user32.dll",SetLastError=true)] public static extern bool EnumChildWindows( IntPtr hWndParent, User32Functions.EnumWindowsCallback lpEnumFunc, IntPtr lParam ); The point is, why do you need to pass a class or struct as the third parameter? I followed the MSDN recommendation and called the function like that: GCHandle gch=GCHandle.Alloc(this.twHandles); User32.EnumChildWindows(handleParent,this.enumThreadCallback,(IntPtr)gch); gch.Free(); Here this.twHandles is a text writer, which i later (in the callback function) use like so: private bool CaptureEnumThreadWindows(int handle, IntPtr param) { GCHandle gch=(GCHandle)param; TextWriter tw=(TextWriter)gch.Target; twHandles.Write(handle.ToString()+" "); twHandles.Flush(); return true; } Anyway, MSDN recommends to use GCHandle , 'so the delegate does not get moved by GC before the call ends, however I was trying to use without GCHandle, just passing IntPtr.Zero as the last parameter and it works anyway. Frankly I don't understand how this (GCHandle) can prevent the delegate from being moved by GC, but that's what MSDN says. (see GCHandle sample)

            S Offline
            S Offline
            shajuMathew
            wrote on last edited by
            #5

            Thanks Ael GCHandle worked well And it solved my problem. Shaju Mathew

            1 Reply Last reply
            0
            • S shajuMathew

              Thanks... Heath Stewart The tips helped .. But i cannot change class to struct. Since struct won't allow the same struct as a member Shaju Mathew

              H Offline
              H Offline
              Heath Stewart
              wrote on last edited by
              #6

              In that case, use a GCHandle to pin the class instance in memory. The GC (Garbage Collector) may relocate the object in memory, so the address would change. Unmanaged code can't deal with those changes so you'll get all sorts of errors since your object isn't where it's supposed to be. You can find more information about the GCHandle class in the .NET Framework SDK.

              Microsoft MVP, Visual C# My Articles

              1 Reply Last reply
              0
              Reply
              • Reply as topic
              Log in to reply
              • Oldest to Newest
              • Newest to Oldest
              • Most Votes


              • Login

              • Don't have an account? Register

              • Login or register to search.
              • First post
                Last post
              0
              • Categories
              • Recent
              • Tags
              • Popular
              • World
              • Users
              • Groups