[Date Prev][Date Next][Thread Prev][Thread Next]
- Subject: Re: Announce - SWIG-1.3.30
- From: Don Hopkins <dhopkins@...>
- Date: Sat, 18 Nov 2006 02:12:53 -0800
Sam Roberts wrote:
On Fri, Nov 17, 2006 at 11:09:39AM -0800, Don Hopkins wrote:
it doesn't require that your code be written in C++, and it doesn't
YMMV. I tried to use swig to bind a C library into ruby for a few days,
and came away pretty frustrated.
I haven't used the Ruby back-end. I hope someone improves it.
SWIG has excellent support for Python, which has a single well defined
Have you tried using SWIG's "shadow classes" with Python?
It's an option you can turn on and off, but I think it's on by default.
SWIG writes some Python source code into a module that defines Python
shadow classes with methods bound to the low level ClassName_MethodName
functions, which you can use as normal classes and subclass properly
Not all SWIG back-ends support shadow classes -- it's an optional
feature depends on the language's class system.
Since Lua has a "roll your own" class system, there's not a lot SWIG can
assume about how you want objects to work, so SWIG's Lua back-end
doesn't currently support that feature, nor does it generate any Lua
wrapper code. But it could!
I've made some modifications and extensions to SWIG, to support my own
quirky object system (which may or may not be how you want to do objects).
I took a good look at tolua++, which is great Lua-savvy code, to pick up
some useful tricks: it uses lua_setfenv to attach a Lua "peer object"
to the userdata's environment.
I modified some of the SWIG runtime templates and made some typemaps to
support wrapping C++ objects with Lua "peer objects" that additionally
inherit from their own Lua classes, and easily call back into user
defined Lua objects from C++.
I posted the code to this list a couple of months ago, I've been using
it, and I'm pretty happy with how it works.
I might have fixed some bugs since then, so just ask and I'll send you a
fresh copy of my changes.
Since everybody wants to roll their own object system in Lua, it would
cool to parameterize the SWIG Lua runtime templates so you can hook in
glue for any object system you want. But for now I just hacked my own in!
Yes, you're right that SWIG is good for heavy duty C++ and best for OO
languages, and it supports some languages better than others, and the
documentation is mediocre.
But it's quite powerful and ambitious: SWIG knows all about the C++ type
system and even templates, and it's based on pattern matching of C++
types and function signatures.
Thanks to the massive complexity of C++, SWIG's learning curve is pretty
steep, and it keeps on going a long way up as it articulates C++'s
byzantine fractal surface area.
It's nice to know all the C++ stuff is there and it does the right thing
when you need it. It even has typemap libraries that support most of the
standard library templates (YYMV depending on the language, of course).
The impression I got was that swig was very good at binding OO C++ into
OO languages (I guess because c++ has enough compiler keywords that make
it clear what is an object, and what the ctor/dtor is, etc.), but what I
had was fairly typical "OO in C" libraries:
typdef struct Foo Foo;
int foo_new(Foo** foo, int arg);
int foo_use(Foo* foo, const char*in, size_t in_sz, char* out, size_t* out_sz);
# non-zero return is an error
void foo_destroy(Foo** foo);
I thought it would be easy to bind, because the library, while having a
lot of APIs, had a very, very consistent set of calling conventions, but
I had trouble finding documentation on this. There was lots of doc
coverage of how to do cool things with C++ and templates, but the simple
case of C libraries was surprisingly under discussed.
Anyhow, I think I could do great things with swig if I knew it well, but
the learning curve was pretty steep at the time. I hand-coded the
It's possible to use SWIG for C stuff (like the Ming library interface)
and simple C++ stuff without worrying about all the advanced C++ stuff
(like Gnu Radio's signal processing module C++ template wrappers).
You can also wrap a low level C library in a simple "SWIG friendly" C++
shell with error checking and bullet proofing so it won't crash or let
you do anything illegal from the scripting language.
I've found an easy way to plug a non-object-oriented C library into an
object oriented language is to write a thin C++ class around it, and
SWIG-ify that C++ class, instead of the raw C library. Then SWIG will
generate shadow classes (if the back-end supports it) that you can
subclass to add new behavior, and use custom methods and properties in
the peer object. Sometimes the library's interface is too low level to
be used conveniently from a scripting language (cough cough Win32 cough
X11 gag). For example, I'm using Cepstral's "Swift" text to speech C
library, and I've written some C++ classes to wrap and simplify the C
interface, which call back into Lua with events during speech synthesis
(phonemes to animate a mouth, bookmarks, etc).
If you expose a bunch of superfluous symbols and useless functions, it
makes your program bigger by writing all those extra wrappers. So make
an "appliance shell" to reduce the API's surface area to just what's
needed. Instead of defining zillions of enumerated symbols, just pass
the symbol names as strings, or pass in structured Lua tables and
objects (if you're willing to write language-specific code).
You can write language-specific typemaps and extension methods that
convert between C++ and native data types (like making structured Lua
tables and manipulating Lua objects). Use typemaps to automatically
convert between C++ types and scripting language types. Use %extend to
extend the wrapper classes with script-friendly utility and convenience
I like to use %extend to add extra "helper functions" into the wrappers
that don't exist in the actual C++ objects, that you can call from the
scripting language. That is really useful when you're trying to make a
script-friendly version of some nasty C++ object you got from somewhere
whose api you don't have control over.