[Mono-list] Re: Calling back from unmanaged code to managed code.

Cory Nelson Cory Nelson <phrosty@gmail.com>
Fri, 17 Dec 2004 06:14:57 -0800


Would be good to note, on Windows, that your C code expecting a
__cdecl or __stdcall function pointer can make all the difference. 
Gave me a nice 2 day long headache with debugging :)


On Thu, 16 Dec 2004 21:04:15 -0500, Jonathan Pryor <jonpryor@vt.edu> wrote:
> Just for "fun", I'll write the equivalent C# declarations inline with
> the C code.  Note that I haven't tried to compile this, but the basic
> idea should be seen...
> 
> On Thu, 2004-12-16 at 13:32 -0500, Nigel Benns wrote:
> > Here is a C example to do a DeleteEvent:
> >
> > void delete_cb(Ewl_Widget *w, void *event, void *data) {
> >     ewl_widget_destroy(w);
> >     ewl_main_quit();
> > }
> 
> delegate void EwlDeleteCallback (IntPtr w, IntPtr event, IntPtr data);
> 
> class MyTest {
> 
>         private const string LIB = "ewl";
> 
>         [DllImport (LIB)]
>         private static extern void ewl_widget_destroy (IntPtr w);
> 
>         [DllImport (LIB)]
>         private static extern void ewl_main_quit ();
> 
>         private void delete_cb (IntPtr w, IntPtr event, IintPtr data)
>         {
>                 ewl_widget_destroy (w);
>                 ewl_main_quit ();
>         }
> 
> > int main(int argc, char **argv) {
> >    ewl_init();
> 
>         [DllImport (LIB)] private static extern void ewl_init ();
> >    ...
> >    win = ewl_window_new();
> 
>         [DllImport (LIB)] private static extern IntPtr ewl_window_new();
> 
> >    ...
> >    /*Where this function appends the callback to a calback list read
> >      by ewl_main().
> >    */
> >    ewl_callback_append(win, EWL_CALLBACK_DELETE_WINDOW, delete_cb, NULL);
> 
>         // Here's what you're interested in:
>         [DllImport(LIB)]
>         private static extern void ewl_callback_append (IntPtr win,
>                 int callback_type, EwlDeleteCallback cb, IntPtr data);
> 
>         // I'd assume that ewl_callback_append can take a variety of
>         // function pointer types (the callback is probably void*),
>         // so you could overload this function for each function
>         // pointer type that ewl_callback_append accepts.
> 
>         // obviously, this needs to be set to the correct value.
>         private const int EWL_CALLBACK_DELETE_WINDOW = 0xdeadbeef;
> 
> >    /*The NULL is for the Data to pass */
> >    ...
> >    ewl_main();
> 
>         [DllImport(LIB)] private static extern void ewl_main ();
> > }
> >
> > Ok, so what I'm trying figure out is how to add the ewl_callback_append as
> > a delegate in C#.
> 
>         public static void Main ()
>         {
>                 ewl_init ();
>                 IntPtr win = ewl_window_new ();
>                 EwlDeleteCallback cb = new EwlDeleteCallback (delete_cb);
>                 ewl_callback_append (win, EWL_CALLBACK_DELETE_WINDOW, 
>                         cb, IntPtr.Zero);
>                 ewl_main ();
>                 System.GC.KeepAlive (cb);
>         }
> }
> 
> Note that the System.GC.KeepAlive is necessary so that the GC doesn't
> collect your delegate before EWL is finished using the function pointer
> it has (the delegate is marshaled as a function pointer).  It would be
> "bad" to have the GC collect the delegate early.
> 
> > It doesn't seem write to me that I could pass a C# function to C, even if
> > I could figure out how to do that?
> 
> You can pass a delegate referring to a C# method to C.
> 
> I would suggest reading my guide, "Everything you (n)ever wanted to know
> about marshaling (and were afraid to ask!)":
> 
>         http://www.jprl.com/~jon/interop.html
> 
> It's also available through monodoc (though the above is more recent --
> I've been lazy about committing):
> 
>         http://www.go-mono.com/docs/index.aspx?tlink=8@xhtml%3anew%2fen%2fprogramming%2finterop.html
> 
> You may also want to look into Gtk#, just to see how the wrapper code
> can be used.
> 
>  - Jon
> 
> 
> _______________________________________________
> Mono-list maillist  -  Mono-list@lists.ximian.com
> http://lists.ximian.com/mailman/listinfo/mono-list
> 


-- 
Cory Nelson
http://www.int64.org