Inline::C for Tcl

Dossy wrote to the ActiveTcl mailing list in 2003:


Hi,

If there's already a project to bring Inline::C capability to Tcl, please point me at it. Otherwise, perhaps this could be the start of one.

For those unfamiliar with what Inline::C is, it is a Perl module that allows you to embed C code within your Perl program -- for more information, look here:

    http://search.cpan.org/author/INGY/Inline-0.44/C/C.pod

Now, tonight, I got to thinking: gee, it'd be nice to have something like this for Tcl. After giving it the "good ol' college try" (you know, I Googled two or three times and nothing came up) I couldn't find an implementation of Inline::C for Tcl. So, I said to myself: Tcl is awesome -- it shouldn't take me more than a minute or two to get a bare minimum snippet of Tcl code working that does what I want.

So, here is my first whack at Inline::C for Tcl: [L1 ]

Again, if such a thing already exists, pointers would be appreciated. Otherwise, perhaps if others find this useful, we can get this added to Tcllib or it can stand on its own. I don't care either way.

-- Dossy


Critcl and tcc4tcl do this and a lot more, but at 50 lines Dossy's code is worth preserving as an illustration of how simple it can be.

Note that this is pure Tcl code, except the call to exec gcc. It assumes that your system is configured so GCC will see the correct Tcl headers.

#
# $Id: inline.tcl,v 1.1.1.1 2003/08/24 04:23:14 dossy Exp $
#

package require Tcl 8

namespace eval ::inline {
    ### Do I need anything here?
}

proc ::inline::c {procName body} {
    set fd [open /tmp/inline-c.c w]

    puts $fd [subst {
#include <tcl.h>

int
${procName}ObjCmd(clientData, interp, objc, objv)
ClientData clientData;
Tcl_Interp *interp;
int objc;
Tcl_Obj *CONST objv[];
{
    $body
}

int
[string totitle $procName]_Init(interp)
Tcl_Interp *interp;
{
    Tcl_CreateObjCommand(interp, "$procName", ${procName}ObjCmd, NULL, NULL);
    return TCL_OK;
}
    }]

    close $fd

    ### FIXME: Platform-dependent.  Needs error checking, too.
    exec gcc -shared -o /tmp/inline-c.so /tmp/inline-c.c

    load /tmp/inline-c.so $procName

    file delete /tmp/inline-c.c /tmp/inline-c.so
}

package provide inline 1.0

And a test program:

    package require inline

    ::inline::c hello {
        Tcl_SetResult(interp, "Hello, world.", TCL_VOLATILE);
        return TCL_OK;
    }

    puts [hello]