Generating C# interfaces the lazy way

on Wednesday, January 02, 2008
Since all this Winforms WebBrowser control / Mono.Mozilla / gluezilla business started, there's one thing that's been nagging me at that place in the brain where I store stuff I'd rather not think about at the moment (and yes, it's a place that quite resembles those junk-filled attics you see in movies where the kids go to play and occasionally encounter old moth-eaten dresses, the occasional treasure map or your garden-variety skeleton of the aunt nobody had seen in 50 years - a stuffy, moldy place where you can't take a step without tripping on something...)...

Where was I? Oh, yes, nagging me was the thought that, while I had successfully created C# interfaces from the mozilla idl files, and was successfully accessing mozilla through XPCOM directly from the managed side, those interfaces were created by hand, which was not that hard at all, and I really could go on doing them by hand, only getting full DOM support on Mono.Mozilla would require generating some 50 interfaces... by hand.... ugh

So, whilst suffering without net last week due to a router dying and a firewall showing solidarity towards said router (i.e., dying too), I ran across some perl scripts that are being used for various tasks all over the mono tree, and decided that enough was enough, I should get it over once and for all and do a little script to parse the idl files and generate my badly needed interfaces.

Queue a fun-filled day playing around with perl, learning from scripts and from what little documentation I could find on my system (no net, no manuals...) In the end, scraped something together which is living on svn in mcs/class/Mono.Mozilla/tools/xpidl2cs

xpidl2cs basically parses an idl file and generates a C# interface that's ready to be used. It goes all the way up the inheritance tree and generates all parents and, since .NET interop doesn't support interface inheritance and requires child interfaces to also include all the declarations from the parent, xpidl2cs recursively includes all the parent declarations, so you end up with a (probably rather) huge but working interface.

xpidl2cs also generates all the interfaces that are used in methods and properties of your target idl (and parents) so that all dependencies are satisfied in one pass. To avoid endless looping on this, the script doesn't generate the interface if a .cs file with the same name already exists in the directory, so if you want to make sure everything is regenerated, you should rm all interfaces first.

The usage is simple: xpidl2cs.pl file.idl [/path/to/idl/files/]

Any bugs, comments, flames, etc, feel free to nag here or on the #mono channel over at irc.gnome.org, or just mail me.

3 comments:

Ricardo said...

Hi Andreia I have been trying to create a multiplatform control to embed gecko and I read everything I can about how to achive this: com, xpcom, mono, mozilla, geckofx, gtk and now I'm kind of lost.
My idea is that the geckofx control is a good staring point and the only thing to make it run everywhere is the xpcom initialization code but this could be achieved by gluezilla on any platform.
Most of the information that I found is about your implementation of mono.webbrowser.
I tried to follow it but looks like it is mostly outdated and the code repositories are gone from their original location.
I think it was because a change in the name of the library but there are some files that I haven't been able find anymore, anywhere like your perl script to generate the cs interfaces or the new equivalent that is mentioned in the com mono documentation .
Could you shed some light on me about all this and give some advice about what you think is the best way to achieve this
Any headups are very much appreciated.

By the way is always nice to have your girl power among us.

pseudofarmerSM said...

Hi,
I was about to email Andreia more or less exactly with the same words...
Add openwebkitsharp and webkitsharp to the bunch.. and xilium cefglue... it's a mess. With MONO 4, onlinux, there doesn't seem to be a single implementation with webbrowsers...
Ricardo, Andreia, do you have any tips? (why does this seem a portuguese thing? :) )

Andreia Gaita said...

The world of embedded browsers is pretty annoying, has been for years. Webkit exposes different APIs depending on the platform and the toolkit, Mozilla killed their embedding API completely, so getting one common api cross-platform is.... annoying, at best.

The only light on the tunnel right now is the webkit gtk variant, which has been ported to osx via macports (and maybe windows??), and for which we have auto-generated bindings for gtk2 and gtk3 at https://github.com/andreiagaita/bindinator and https://github.com/xDarkice/bindinator (gtk# at https://github.com/mono/gtk-sharp)