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/[EMAIL PROTECTED]

You may also want to look into Gtk#, just to see how the wrapper code
can be used.

 - Jon


_______________________________________________
Mono-list maillist  -  [EMAIL PROTECTED]
http://lists.ximian.com/mailman/listinfo/mono-list

Reply via email to