Embedded Lua doesn't print to dedicated console
My code looks like this (Windows platform):
AllocConsole();
FILE *fp = freopen("CONOUT$", "w", stdout); //couldn't find documentation what CONOUT$ actually is
lua_State *lua_state = luaL_newstate();
luaL_openlibs(lua_state);
if(luaL_dostring(lua_state, "print 'It works!'"))
{
printf("%s\n", lua_tostring(lua_state, -1));
}
I cannot get Lua output while normal printf is running (Lua errors are also displayed)
source to share
TL; The DR: . The program uses more than one version of the C runtime library. Don't do this. This always leads to mysterious symptoms from another correct code.
Background
At first glance, your code should work. And, if you build and maintain this, I can make it work. For reference, I am building MingW GCC 4.7.2 for 32-bit Windows on Win7 Pro. But I believe that the main problem can occur with any compiler targeting Windows.
I'm going to go through the process of finding this error, in the hope that it will be helpful to see how I figured it out. But if you're impatient, skip to the end and then come back here to see how I got there.
Controlled code
First, I wrapped the code snippet in enough boiler plates to compile and run:
#include <lua.h>
#include <lauxlib.h>
#include <stdio.h>
#include <windows.h>
int main(int argc, char **argv) {
AllocConsole();
FILE *fp = freopen("CONOUT$", "w", stdout);
lua_State *L = luaL_newstate();
luaL_openlibs(L);
if(luaL_dostring(L,
"print 'print works!'\n"
"io.write 'io.write works'"
))
{
printf("%s\n", lua_tostring(L, -1));
}
Sleep(5000); // give me 5 seconds to read the console
}
Compiling with GCC
I compiled and linked as easily as possible with Windows, which is not too bad since I have a copy of Lua for Windows which turns out to leave an environment variable LUA_DEV
pointing to it being installed:
gcc -o q15787892 q15787892.c -mwindows -I"%LUA_DEV%\include" "%LUA_DEV%\lua5.1.dll"
The flag -mwindows
tells GCC (specifically the linker ld
) to mark the executable as a complete Windows GUI program. Without this flag, you end up with a console program that already has a console assigned, and AllocConsole () will simply provide descriptors to the one containing the command line.
results
Interestingly, neither the call print()
nor io.write()
output the result. I entered a syntax error in the Lua text and noted that it did output to the console, showing that it was stdout
indeed redirected correctly.
I added FILE *old=stdout;
before freopen()
and printf("%p %p %p", fp, stdout, oldstdout);
after the call . All three pointers were exactly equal, indicating that he freopen()
hadn't done something out of the ordinary.
In the sources for implementing Lua 5.1, print()
we find that it just calls fputs(s,stdout)
.
So how is it possible that a call printf()
from main()
works, but a similar call using use stdout
fails?
Decision
Perhaps, if stdout
in main()
does not match with stdout
in luaB_print()
.
But both are global variables and the linker has to make them the same, right?
Well, not necessarily. The global variable stdout
is part of the C runtime library. If the Lua kernel is linked to a different C runtime library than the program, then it is possible that the Lua kernel and the program actually refer to different named variables stdout
.
A quick check with Dependency Walker reveals that my test executable was linked to MSVCRT.DLL (C runtime preferred by MinGW), but lua5.1.dll
from Lua for Windows it was linked to MSVCR80.DLL (C runtime from Visual Studio 2005).
This problem is easily solved. I modified my test case to link to the Lua assembly linked to MSVCRT.DLL and now the source code works as intended. Here's the new build steps now in the BAT file and assuming it lua5_1-4_Win32_dll6_lib
contains a well-built Lua core:
setlocal
set LUADIR="lua5_1_4_Win32_dll6_lib"
gcc -o q15787892 q15787892.c -mwindows -I"%LUADIR%\include" "%LUADIR%\lua5.1.dll"
if not exist lua5.1.dll copy %LUADIR%\lua5.1.dll .
source to share