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; }