Reputation: 882
My code looks like that (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 can't get Lua output, while normal printf works (Lua errors are also printed)
Upvotes: 1
Views: 1822
Reputation: 57
Another possible reason is that luaxx.dll is released,and the test project is debuged version.So,luaxx.dll uses msvcrxx.dll,but the test project uses msvcrxxd.dll--the debuged version of microsoft c runtime.
Upvotes: 0
Reputation: 43326
TL;DR: The program is using more than one version of the C runtime library. Don't do that. It always leads to mysterious symptoms from otherwise correct code.
On the face of it, the code you present should work. And, if built and linked with care here, I can make it work. For reference, I'm building with MingW GCC 4.7.2, for 32-bit Windows, on Win7 Pro. But I believe the underlying issue can occur with any compiler targeting Windows.
I'm going to walk through the process of finding this bug, in the hope that it is helpful to see how I figured this out. But if you are impatient, skip to the end, then come back here to see how I got there.
First, I wrapped your code fragment in enough boiler plate to make it compile and run at all:
#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
}
I compiled and linked about as simply as possible on Windows, which isn't too bad since I have a copy of Lua for Windows installed which happens to leave the environment variable LUA_DEV
pointing at its installation:
gcc -o q15787892 q15787892.c -mwindows -I"%LUA_DEV%\include" "%LUA_DEV%\lua5.1.dll"
The -mwindows
flag tells GCC (specifically the linker ld
) to mark the executable as a full Windows GUI program. Without that flag, you get a console program that already has a Console assigned and AllocConsole() will simply provide handles to the one holding the command prompt.
Interestingly, neither the call to print()
nor io.write()
produced output. I introduced a syntax error in the Lua text and noted that it did output to the console, showing that stdout
really was redirected correctly.
I added FILE *old=stdout;
before the call to freopen()
and printf("%p %p %p", fp, stdout, oldstdout);
after it. All three pointers were exactly equal, showing that freopen()
didn't do something unusual.
Looking in the sources to Lua 5.1's implementation of the print()
function we find that it simply calls fputs(s,stdout)
.
So how is it possible that a call to printf()
from main()
works, but a similar call using stdout
fails?
It is possible if stdout
in main()
is not the same as stdout
in luaB_print()
.
But both are global variables, and the linker is supposed to make them be the same, right?
Well, not necessarily. The global variable stdout
is part of the C runtime library. If the Lua core is linked to a different C runtime DLL than the program, then it is possible that Lua core and the program are in fact referring to different variables named stdout
.
A quick check with Dependency Walker shows that my test executable was linked against MSVCRT.DLL (the C runtime preferred by MinGW), but the lua5.1.dll
from Lua for Windows is linked against MSVCR80.DLL (the C runtime from Visual Studio 2005).
This problem is easily resolved. I changed my test case to link against a build of Lua linked against MSVCRT.DLL, and now the original code works as intended. Here's the new build steps, now found in a BAT file, and assuming that lua5_1-4_Win32_dll6_lib
contains the correctly 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 .
Upvotes: 6