[Gtk-sharp-list] Design for Indexer for GLib.List to allow [] based addressing.

Daniel Kornhauser dkor@media.mit.edu
Tue, 21 Oct 2003 16:39:15 -0400


In this mail I'm going to write about the thought process that a newbie
has to try to solve a bug (it's actually only a customization). I'm
sorry if it's really off topic, but I think it's interesting to share
the process that you go by trying to solve a bug instead of just posting
a solution of what you think is a plausible bug solution. mkestner and
tberman for the desing and code just skip the code until the last part.

The process
============

I was on the mono irc, and suddenly, --splash--, miguel suggest to
mkestner I should try to solve some bugs for mkesnter. I start trembling
since I've only done hight demo gtk# coding. Then mkenster replies ´why
don't you do 47956¡, and I get the following advices: 


<mkestner> dkor: I think the request is basically to a this[] property
to access list elements by pinvoke

<tberman> should be: public object this[int index] { get { //code; } }

<mkestner> and it calls g_list_nth_data or g_slist_nth_data, or whatever
list type it is implemented for

<dkor> ok, I understand that :-)

<mkestner> but it has to take into account whether an element_type has
been provided, so it knows how to "wrap" the list elements

<mkestner> I have to run, but I'd suggest posting a "design" to the bug
once you've got a plan, and tberman and I can comment on it. Thanks for
taking a look at it.



I run off to bugzilla.ximian.com and read my first bug :


Indexer for GLib.List to allow [] based addressing.
If i get the time, I will attempt this and submit a patch on this bug.

But I'm a mortal and the first time I read this I didn't know what the
hell it meant. I guessed something like, a GLib.List should be handled
like a normal C# List. So how should I do that. I rember the advice of
tberman:

<tberman> should be: public object this[int index] { get { //code; } }

I run of to the C# Essentials and discover indexers: ¡a natural way to
index elements using the open and colsed bracket [] syntax¡



So where to start?


First I try to find some code that is pertinent to the bug. I off course
use some ´du -a | grep List¡ on the cvs and find lots of files that
contain the List word. Then I just go to cvs/gtk-sharp/glib, and find
the relevant files:

List.cs

SList.cs

BaseList.cs


I go to the List.cs source, and see it's using some kind of
InteropServices. So I go to the ´Programming in the .Net Environment¡
book, and find out that it uses uses Pinvoke to directly to invoke
directly the functions GList methods. I must say that Pinvoke is kind of
magic. I just four lines you can access a C function from C#. Humm, but
it's still not clear how a List.cs works.


So I decided to get some more information. I search thought the mailing
list some mails, I read lot's of discussion of how to wrap GLib.List and
understand half of it, but it still leaves me in the dark of how List.cs
works. 


Thus I decide to look how a GLib.List is instanced. I go to look at the
constructor of that GLib.List, and find out that the construction is
actually instanced from ListBase.cs . In ListBase it's still not clear
how the list is instanced. So go to the C GLib Reference and find out
that it doesn't even get instanced in C, you just declare setting a
GList* to NULL. 


So Now I have learned that there is actually lot of interaction between
List.cs and ListBase.cs. Actually List.cs only returns pointer from
wrappers to Glist to the ListBase.cs method.


Now , I search for a similar function that returns an element of the
list in monodoc and I see that Current is the way that you get data out
of a list.

Now it's more clear. List.cs inherits Current from ListBase.cs, and uses
the GetData to access the data thought gtksharp_list_get_data.


Still I didn't understood why the Pinvoke wasn't direclty to a
"libglib-2.0-0.dll" fuction and there have to be the existence of an
auxiliary function "gtksharpglue" until mkestner explained to me that
there wasn't an explicty stated.


<mkestner> dkor: glue is just there to provide a pinvoke target for
things that don't already have methods

Desing
======

Now it's pretty clear what I think I have to do:

      * Create a wrapper around the g_list_nth_data or g_slist_nth_data
        functions in List.cs and Slist.cs using directly Pinvoke.
        
      * Create an Indexer in ListBase.cs using as a template the
        --public object Current-- method in ListBase.cs
        
        

The code :
==========

In ListBase.cs


public object this[int index] { 
    get {  
	IntPtr data = list.NthData (index);
	object ret = null;
	if (list.element_type != null)
	    {
		    if (list.element_type == typeof (string))
			    ret = Marshal.PtrToStringAnsi (data);
		    else if (list.element_type == typeof (int))
			    ret = (int) data;
		    else if (list.element_type.IsValueType)
			    ret = Marshal.PtrToStructure (data,
							  list.element_type);
		    else
			    ret = Activator.CreateInstance (
							    list.element_type,
							    new object[] {data});
	     }
	else if (Object.IsObject (data))
		ret = GLib.Object.GetObject (data, false);
	
	return ret;
	
    }
}


In List.cs

        [DllImport("libglib-2.0-0.dll")]
        static extern IntPtr g_list_nth_data (IntPtr l, uint n);

        internal override IntPtr g_list_nth_data NthData (IntPtr list, uint n)
        {
                return g_list_nth_data ();
        }



Conclusion:
===========

If you are a newbie to gtk# hacking there is plenty of resource for
understanding gtk# you just need to be aware of them and fairly auto
didactic.
Allways use

	- grep
	- get the cvs code
	- monodoc 
	- go www.gtk.org

I should be more explicit
BUT
Now I have to run !!!!
                                      Daniel