Warning: this is an htmlized version!
The original is here, and
the conversion rules are here.
/*
 * luatclbridge.c - a Lua<->Tcl bridge.
 * By Eduardo Ochs <[email protected]>
 * Version: 2007aug14
 * http://angg.twu.net/LUA/luatclbridge.c
 * http://angg.twu.net/LUA/luatclbridge.c.html
 * (find-es "lua5" "luatclbridge")
 * (find-es "lua5" "tlbridge.c")
 * (find-angg "LUA/lua50init.lua" "loadtcl")
 *
 * Note: some inter-language bridges - for example, lunatic-python -
 * can be loaded from both interpreters; this one cannot, you need to
 * load it from the Lua side.
 *
 * This is a very minimalistic two-way bridge between Lua and Tcl. It
 * adds one global function to Lua ("tcl", to call Tcl), and one to
 * Tcl ("lua", to call Lua); none of them check for errors, and if you
 * are running code in the other language that may fail in nasty ways
 * then you should implement your own wrappers - called, say, "plua"
 * and "ptcl", that execute functions in the other language with some
 * kind of protection. I believe that these wrappers should be easy
 * enough to write in Lua and Tcl, without the need for more C code;
 * and the simpler we can keep the part in C the better - many more
 * people can understand the parts in Tcl and Lua than the part in C.
 *
 * NOTE: There were two natural choices for how to call Tcl from Lua:
 *   tcl("expr", "12+34")    -- <-- I have NOT chosen this
 *   tcl("expr 12+34")       -- <-- I have chosen this one.
*/


#include <stdio.h>
#include <tcl.h>
#include <lua.h>
#include <lauxlib.h>

/* interpreters */
lua_State  *LuaTclBridge_L; 
Tcl_Interp *LuaTclBridge_T;


/* Tcl -> Lua
 * Example of use:
 *   lua print 22 {foo bar}
 * this calls the global Lua function called "print"
 * with arguments "22" and "foo bar".
 * The value returned to Tcl is always the frist value returned by the
 * Lua function, converted to a string with lua_tostring; so this
 * returns "nil" (yes, as a string!...).
 */
int LuaTclBridge_call_lua(ClientData clientData, Tcl_Interp *interp,
		int argc, const char *argv[]) {
  lua_State *L = LuaTclBridge_L;
  int i;
  //
  // (find-luamanualw3m "#lua_call")
  lua_getfield(L, LUA_GLOBALSINDEX, argv[1]); // push first arg as a function
  for (i=2; i<argc; ++i)		      // for each one of the other args
    lua_pushstring(L, argv[i]);		      // push it as a string
  lua_call(L, argc - 2, 1);		      // call - expect one result
  //
  // Now return a string result to Tcl...
  // (find-man "3tcl Tcl_SetResult" "THE TCL_FREEPROC ARGUMENT" "TCL_VOLATILE")
  Tcl_SetResult(interp, lua_tostring(L, 1), TCL_VOLATILE);
  //
  // We're always returning TCL_OK at this moment...
  // What should we do when the call to Lua triggers an error?
  // Right now we just expect the user to be super-careful...
  // (find-man "3tcl Tcl_Eval" "TCL_OK")
  return TCL_OK;
}


/* Lua -> Tcl
 * Example of use:
 *   tcl("expr 22+33")
 * returns "55".
 *
 * Note that this function receives a single argument, a string to
 * execute as a Tcl program - not a series of strings, each one being
 * a word of a Tcl command.
 */
int LuaTclBridge_call_tcl(lua_State *L) {
  if (!LuaTclBridge_L)
    LuaTclBridge_L = L;
  if (!LuaTclBridge_T) {
    // Tcl_FindExecutable(argv[0]);  <-- a bit of black magic, see my tcl.e
    // Tcl_FindExecutable("");
    LuaTclBridge_T = Tcl_CreateInterp();
    Tcl_CreateCommand(LuaTclBridge_T, "lua", LuaTclBridge_call_lua,
		      (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
  }
  Tcl_Eval(LuaTclBridge_T, luaL_checklstring(L, 1, NULL));
  lua_pushstring(L, Tcl_GetStringResult(LuaTclBridge_T));
  return 1;
}


/* Experimental, 2007aug14
 */
static int LuaTclBridge_tclfindexecutable(lua_State *L) {
  Tcl_FindExecutable(luaL_checklstring(L, 1, NULL));
  return 0;
}




/* initalization.
 * Usage:
 *   tcl = require "tlbridge"
 *   print(tcl("expr 22+33"))  -> "55"
 */
LUALIB_API int luaopen_luatclbridge (lua_State *L) {
  lua_pushcfunction(L, LuaTclBridge_call_tcl);
  lua_pushcfunction(L, LuaTclBridge_tclfindexecutable);
  return 2;
}