5

I have a c program running embedded Lua. as of right now, it's just a hello world. before moving on, though, I'd like to be able to get the lua output to be sent somewhere other than stdout, so that I can manipulate it in some manner. Here's my code:

#include <stdio.h>

#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>

int main() {
    lua_State *luaVM = luaL_newstate();
    //char result[1024];

    if (luaVM == NULL) {
        printf("Error initializing lua!\n");
        return -1;
    }
    luaL_openlibs(luaVM);
    luaL_dostring(luaVM, "print(\"hello world!\")");
    //Somehow put the output into result

    //printf("%s\n%s\n", result, result);

    lua_close(luaVM);
    return 0;
}

For example, I'd like to use result, seen in the comments, to print the result of the lua code twice. Can this be done?

ewok
  • 20,148
  • 51
  • 149
  • 254
  • I've done that in the past. You will need to patch Lua to achieve this. What version are you using? My patch is for Lua 5.1, but I could port it for 5.2 as well. – Andrejs Cainikovs Aug 09 '12 at 14:57
  • I'm using 5.2. Is this really not possible as an option in the C API? – ewok Aug 09 '12 at 15:03
  • You know, other than completely rerouting `stdout`, which I would greatly prefer to avoid – ewok Aug 09 '12 at 15:03
  • My patch was about redefining the output functions to hooks, and then setting those from application or intermediate library, so you could use your custom output functions. – Andrejs Cainikovs Aug 09 '12 at 15:16
  • @AndrejsCainikovs I don't understand. I want to avoid rerouting `stdout` to a custom stream, as I use `stdout` for debugging purposes, and would like to avoid switching back and forth all the time. does your patch allow me to do this? – ewok Aug 09 '12 at 15:18
  • Yes. My patch allows you to use custom output functions, specifically designed for Lua, they do not touch standard streams. Please tell me if you're interested in having them, as I'll need to do some work on this :) – Andrejs Cainikovs Aug 09 '12 at 15:31
  • @AndrejsCainikovs yes. this patch sounds like what I need – ewok Aug 09 '12 at 15:36
  • Ok, let me bake it for you. This will take some time. – Andrejs Cainikovs Aug 09 '12 at 15:39

3 Answers3

7

If your Lua code is going to be using print to output stuff, then I guess the simplest way is to redefine print from Lua itself. Something like this:

print_stdout = print -- in case you need the old behavior

print = function(...)
  for arg,_ in ipairs({...}) do
    -- write arg to any file/stream you want here
  end
end
kikito
  • 51,734
  • 32
  • 149
  • 189
  • This seems like its along the lines of what I'm going for, but I need to know how to, for lack of a better term, "return" the output from `luaL_dofile()` to a `char*` in C. can this be done this way? – ewok Aug 09 '12 at 15:27
  • What if Lua script contains syntax error? You'll need to patch Lua if you want to obtain the error in buffer rather than on stdout/stderr. – Andrejs Cainikovs Aug 09 '12 at 15:33
  • @ewok luaL_dofile() does not write to stdout. What do you mean by "output"? – kikito Aug 09 '12 at 16:23
  • @kikito, but `luaL_dostring()` seems to. look at my code. that code causes "hello world!" to be written to the console. I want it in a `char*` – ewok Aug 09 '12 at 16:25
  • @ewok In that case you must redefine print from C, so that it writes to a buffer. See Mike M.'s answer here: http://stackoverflow.com/questions/4508119/redirecting-redefining-print-for-embedded-lua – kikito Aug 09 '12 at 16:31
5

This answer can get critics from some readers, but first please have a look at my blog post which I've prepared specially for this answer, and read the foreword why I choose this solution.

As promised, I've upstreamed my old Lua 5.1 output redirection patch to the latest version.
Patches are available here: 5.1.5 and 5.2.1.

Patch:

patch -p1 < ~/download/lua-5.2.1-output-redirect.patch

Build:

cd src  
make a LUA_A="liblua-5.2.1-redirect.a" SYSCFLAGS="-DLUA_USE_LINUX -DLUA_REDIRECT" SYSLIBS="-Wl,-E -ldl -lreadline -lncurses"

Check:

nm liblua-5.x.y-redirect.a | grep printf
nm liblua-5.x.y-redirect.a | grep fputs
nm liblua-5.x.y-redirect.a | grep fwrite

Test:

Obtain test program here (C/C++ mixed, sorry). Build it via:

g++ -DLUA_REDIRECT -I/path/to/lua-5.2.1/src/ -L. lua-redirect-test.cpp -llua-5.2.1-redirect -ldl -o lua-redirect-test  

Output:

===== Test 1 output =====
Lua stdout buffer:
---
hello world!

---
Lua stderr buffer:
---

---
Lua error message:
---
(null)
---
===== Test 2 output =====
Lua stdout buffer:
---

---
Lua stderr buffer:
---

---
Lua error message:
---
[string "bad_function()"]:1: attempt to call global 'bad_function' (a nil value)
---
Andrejs Cainikovs
  • 27,428
  • 2
  • 75
  • 95
2

Lua's I/O library probably covers what you're looking for. The io.output function lets you set the default output file. Check out the I/O library section in the 5.2 manual to see what else is there.

Why do you want to reroute the output? You say you want to manipulate it in some way, but what do you mean by that?

T Suds
  • 317
  • 2
  • 7
  • 1
    The goal is to have the output A) displayed in a gui, rather than the console and B) with certain functions, have calculations done in C before being displayed – ewok Aug 10 '12 at 17:34