fredrik.eriksson

Coffee and a keyboard

Closures in C

Closures is that (ECMAScript, C#, C) allows inner functions; function definitions and function expressions that are inside the function bodies of other functions. And that those inner functions are allowed access to all of the local variables, parameters and declared inner functions within their outer function(s). A closure is formed when one of those inner functions is made accessible outside of the function in which it was contained, so that it may e executed after the outer function has returned. At which point it still has access to the local variables, parameters and inner function declarations of its outer function. Those local variables, parameter and function declaration have the values that they had when the outer function returned and may be interacted with by the inner function.

I think this simple make count example demonstrates how closures are used in three different language very well.

The make counter declares a local count variable that takes a initial start value, the functional also contains a inner function declaration of function f that increments that count. Function f is then returned a closure is created.

We can now invoke make counter and get the counter method back, we can then invoke the counter function to increment the count value.

This is the makeCounter method in ECMA(Java)Script:

function makeCounter() {
    var count = 0;
    return f;

    function f() {
        return count++;
    }
}

var count = 10;
var counter = makeCounter();
document.writeln(counter());
document.writeln(counter());
document.writeln(counter());

var count = 10;
var counter = makeCounter();
document.writeln(counter());
document.writeln(counter());
document.writeln(counter());
This is the MakeCounter method in C#:
class MainClass
{
    public static Func<int> MakeCounter(int start)
    {
        var count = start;
        var f = () => count++;
        return f;
    }

    public static void Main(string[] args)
    {
        var counter = MakeCounter(10);

        Console.WriteLine(counter());
        Console.WriteLine(counter());
        Console.WriteLine(counter());

        counter = MakeCounter(10);
        Console.WriteLine(counter());
        Console.WriteLine(counter());
        Console.WriteLine(counter());
    }
}

And last makeCount in C this is GCC only feature using the GCC C extension Nested Functions (-fnested-functions)

// gcc closure.c -fnested-functions

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef int (*func_t)(  );

struct trampoline_code
{
    char mov_ecx;
    unsigned char *frame_start;
    char jmp_func;
    unsigned char *func_offset;
} __attribute__((packed)) ;

func_t
make_closure( func_t f )
{
    struct trampoline_code *src = (struct trampoline_code*)f;
    unsigned char *tramp_start = (unsigned char*)src;
    unsigned char *frame_start = src->frame_start;
    unsigned int frame_size = tramp_start-frame_start;
    unsigned char *off;

    unsigned char *frame = malloc( frame_size );

    struct trampoline_code *dst = malloc( sizeof(struct trampoline_code) );
    memcpy( frame, frame_start, frame_size );
    dst->mov_ecx = -71;
    dst->jmp_func = -23;
    dst->frame_start = frame;
    off = (unsigned int)src->func_offset + (unsigned char*)src;
    dst->func_offset = off - (unsigned int)dst;

    return (func_t)dst;
}

func_t makeCounter(int start)
{
    int count = start;

    int f( ) { return ++count; }

    return make_closure( f );
}

int main()
{
    func_t counter = makeCounter( 10 );

    printf( "%d\n", counter() );
    printf( "%d\n", counter() );
    printf( "%d\n", counter() );

    counter = makeCounter( 10 );

    printf( "%d\n", counter() );
    printf( "%d\n", counter() );
    printf( "%d\n", counter() );

    return 0;
}