Closures In Straight C

Jun 9, 01:19 AM by David Caldwell

I’ve read a lot lately about closures. I’ve read articles where people wonder what they are, others where someone is lamenting the fact that they only recently discovered them. I too only recently dicovered the joy of closures. I’ve been writing a lot of javascript recently and I love the way writing anonymous callback functions works. But it turns out I have already been using closures for a long, long time.

A friend and I were discussing C (our language of choice for embedded programming) and the things we like about it and somehow the subject of closures came up. I started thinking about what it would take to implement closures in C. Would you do it in the compiler as a language extention or just build them up by hand using in C itself in a cross-platform way?

And then it struck me: I’ve already been using, in straight, boring old C, the concept of closures. And I’ve been using them practically forever. I would say almost since I first learned C on my Macintosh back in high school.

The original Mac API (which still mostly lives on in Mac OS X’s “carbon” API) has an element in almost every major structure called “refCon”. The Apple documentation sorted of glazed over them (or maybe I glazed over when reading about them) and so I puzzled over these for a long time until I realized that they were pieces of memory that the Mac system would never look at or change. They are for the application writer to use as they see fit.

Apple also uses them when you register a function that the system will call at some later time. Here’s an example I grabbed from the current carbon window manager documentation:


OSStatus InstallWindowContentPaintProc(WindowRef window, 
                                       WindowPaintUPP paintProc, 
                                       WindowPaintProcOptions options, 
                                       void *refCon);

What might you use one for? Well typically you’d create a structure with whatever local data needs to be associated with the call back function and put the pointer to that structure into the refCon. The callback function (since you’re writing it) knows to cast the refCon to the appropriate structure pointer so that it can get access to the fields of the structure.

This is by no means some great thing that Apple discovered. Almost every C API that has callbacks uses the same sort of concept. Here’s a function prototype from glib (one of the gnome base libraries):


guint g_io_add_watch(GIOChannel *channel,
                     GIOCondition condition,
                     GIOFunc func,
                     gpointer user_data);

Here “user_data” serves the same purpose as “refCon” did in the first example. The function you pass in “func” will get “user_data” passed to it (unmolested) by glib.

I’ve used this in almost every API I’ve ever written that has callbacks. Here’s another example from an embedded project I’m working on:


void add_timer(int (*timer)(), void *cookie, int timeout_ms);

I always name my refCons “cookie”, for some reason. Arguably “user_data” is a more descriptive name, but I sort of like the arbitrariness of “cookie”. Or maybe it just makes me think of cookies… MMMM… Cooookies…

So when I learned javascript and started coding Green Felt I wrote a little XMLHttp() wrapper to make the interface nicer (like every other ajax developer on the planet) and I put in a cookie. Later I realized that everything I was passing in the cookie was a local variable and therefore was already saved in the closure. So passing it explicitly through my ajax function was pointless.

It turns out that all those “cookie”, “user_data”, and “refCon” pointers that I had been using since I first learned C transform the user supplied function pointers into “closures”. They do it explicitly and without any syntactic sugar, but they are 100% the same conceptually. In effect you allocate some memory, put references to some of your local variables into the structure and then pass the structure along with the function pointer to be called back later. The callback can use the structure all it wants which ends up being equivalent to a real closure having direct access to those same local variables.

So… Closures aren’t anything new. C has had closures forever. Yes, you have to manually allocate and deallocate the memory for your variables without syntactic sugar… But, hey, that’s C!

Tell the world: technorati related  |  del.icio.us bookmark it!  |  digg digg it!  |  reddit reddit!

  1. This isn’t really closure – you have to manually create the environment you want to capture (your struct) and make it have dynamic extent(stuff it at file scope or malloc it).

    Extremly painful compared to languages with real closures.


    — ratatask    Jun 9, 11:41 PM    #
  2. Those are just pointers to data. A closure has to ‘close over’ its lexical scope, restoring its state and scope at run time.


    Blake Watters    Jun 10, 12:33 AM    #
  3. Thirded. Not even close to closures.


    Ryan Davis    Jun 10, 12:37 AM    #
  4. But you see, that is my point. The “closing over itself” is just syntactic sugar.

    C only supports 2 types of variables. Global variables and stack based local variables. Anything more than that is supported by the standard library—malloc, to be specific.

    The point is that you have to hand hold C to get anything that lasts longer than a local stack variable but shorter than a global variable (which lasts forever).

    By passing these user data pointers around with the function pointer itself, you are effectively passing around your local lexical environment—just the parts you care about.

    Like you guys pointed out (and as I said in the article), it’s painful to do compared to a language with language level closures.

    But that’s the way it is with C for practically everything! It’s the exact same concept as a closure, regardless of how much extra you have to do to implement it…


    — David    Jun 10, 02:07 AM    #
  5. The difference is the same as between “I want X, Y and Z” and “I want everything”.

    If you only want X, Y and Z in the first place, that’s going to be fine, it will work in that limited case. But I don’t know how you’d express “everything” in C.

    What you want is a pointer to the current scope, not a pointer to a copy of some of the variables from the current scope.

    Douglas


    — Douglas    Jun 10, 04:13 AM    #
  6. Douglas, I’m not sure what you mean by “everything”. Please explain.

    You could keep a pointer to you local variables (if you were sure the callback were going to happen before they go away) or you could use the variables in the created structure instead of locals (this is what C folk tend to do in these cases).


    — David    Jun 11, 12:39 PM    #
  Textile Help