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

Nigel Benns nigel_benns@rogers.com
Fri, 17 Dec 2004 09:08:02 -0500 (EST)


Thanks Johnathan, That couldn't have been explained better :)
And your article is very good, there should be a lot that will apply to
what I'm doing, so I've skimmed it for now, and bookmarked it for later.

I'll try what you showed me after work today, and with any luck you may
see an ewl-sharp alpha library available soon for all of those
Enlightenment DR17 fanactics out there!!!!

This will be my first set of libs like this, so I have a lot to learn,
I've downloaded the sourcecode for gtk-sharp and it proves helpful, and
I'm sure I'll be asking them a lot of questions along the way about how
they tackled some issues.

I'm sure I'll be shooting out a lot of emails on the mono lists and
enlightenment lists so I know this won't be the last you hear from me.

I've never been on a mailing list before mono, and I must say, I never
TRUELY new what opensource was all about until I joined.

Thanks again, Nigel

> 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
>