Scripting with Tcl and SWIG
Wednesday Jun 23, 2004
Lately I've been on a mission to provide a scripting interface to a test program that has a curses-based configuration tool that for some reason I have a lot of trouble with. I guess the designer and I have different ideas of how to design a curses-based configuration tool. Alos, the tool produces configuration files that, while they are in ASCII and can be read, they're not easily modified, so difficult to use for scripting.
I'm a fan of Tcl/Tk and also [incr Tcl], which is an object oriented extension to Tcl. [incr Tcl] seems ideal for dealing with structures and things you might want to do to them, or, in object oriented speak, methods you want them to do to themselves, I suppose. Well, how do you connect an existing program with a scripting language like Tcl? Particularly since Tcl doesn't understand what to do with C structures? There's this really cool tool called SWIG, or Simplified Wrapper and Interface Generator. Not only can it generate Tcl and [incr Tcl] code to interface with a program or libraries data structures, but it can handle many other scripting language, including Perl, Python, Ruby, and PHP. Since the only one of these languages I really know is Tcl (I know, it's a hole in my personal knowledge base), I'm using SWIG to generate Tcl and [incr Tcl] code. SWIG is pretty good at understanding structures with relatively basic types, like int, double, char, etc., and simple pointers types. But when it gets to something like char *foo[1024], i.e. an array of 1024 pointers to char, it needs some help. That's where you start using typemaps to convert from C types to scripting language types and back. While Tcl has arrays, they're associative arrays, i.e. their indices can be any string. C's arrays have numeric indices starting at 0. While it seems to me conceivable that you could map those numeric indices to their string counterparts, i.e. 0 to "0", 1 to "1", etc., SWIG doesn't seem to have a way to do that. At any rate, I decided to convert my global char *foo[1024] to a Tcl list when foo is referenced, and convert from a Tcl list to the C array when setting. Works really well, when it works. I'll have another posting about using MDB to figure out why it wasn't working! So what would be the alternative to SWIG? Write your own interfaces to the various structures. SWIG makes this really easy and is a big productivity booster.










