Tech Off Post

Single Post Permalink

View Thread: .NET Gurus: Pinning a delegate for P/Invoke
  • User profile image
    PhrostByte

    Declare your function pointer as typedef void (*FuncPtr)(int i);


    Rossj wrote:
    PhrostByte wrote: Probably not, but the exception is still being thrown Sad  Anyone have a solution?


    I wrote a simple bit of code to replicate this and it works, or rather I can replicate either of the two problems you mentioned.  Without the GCHandle a NPE is thrown in the dllimport'ed function that calls the delegate from C (after it has actually done the callback), and with the handle I get ArgumentException thrown about non-blittable types.

    Please forgive the ugly code ..

    C code wrote:
    #include <windows.h>

    typedef void FuncPtr( int i );

    FuncPtr *cb;

    __declspec( dllexport )
    void SetCallback( FuncPtr ptr )
    {
        cb = &ptr;
    }

    __declspec( dllexport )
    void SomeFunc()
    {
        if ( *cb ) {
            *cb( 10 );        
        }
    }


    C# wrote:
        class Class1
        {
            public delegate void MyDelegate( int i );

            MyDelegate deleg;
    //        GCHandle handle;

            public Class1()
            {
                deleg = new MyDelegate( SomeCallback );

    //            handle = GCHandle.Alloc( deleg, GCHandleType.Pinned );
                SetCallback( deleg );
            }

            // Calls into native code to fire the callback
            public void WorkerMethod()
            {
                SomeFunc();
            }

            public void Close()
            {
    //            handle.Free();
            }

            [DllImport("nativecode.dll")]
            public static extern void SetCallback( MyDelegate d );

            [DllImport("nativecode.dll")]
            public static extern void SomeFunc();


            public static void SomeCallback( int i )
            {
                Console.WriteLine( "Callback " + i.ToString() );
            }
           

            [STAThread]
            static void Main(string[] args)
            {
                Class1 c = new Class1();
                c.WorkerMethod();
                c.Close();
            }
        }