user206334
user206334

Reputation: 882

Embedded Lua does not print to allocated console

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

Answers (2)

newbie
newbie

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

RBerteig
RBerteig

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.

Background

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.

Testable Code

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
}

Compilation with GCC

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.

Results

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?

Solution

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

Related Questions