[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