嵌入式Lua不会打印到分配的控制台

时间:2013-04-03 12:53:03

标签: windows console lua stdout

我的代码看起来像那样(Windows平台):

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

我无法获得Lua输出,而普通的printf工作(也打印了Lua错误)

2 个答案:

答案 0 :(得分:4)

TL; DR:该程序正在使用多个版本的C运行时库。不要那样做。它总是会导致其他正确代码的神秘症状。

背景

从表面上看,您提供的代码应该有效。而且,如果在这里建立和链接,我可以使它工作。作为参考,我在Win7 Pro上使用MingW GCC 4.7.2构建32位Windows。但我相信任何针对Windows的编译器都会出现潜在问题。

我将逐步完成查找此错误的过程,希望看到我如何解决这个问题会有所帮助。但如果你不耐烦,请跳到最后,然后回到这里看看我是如何到达那里的。

可测试代码

首先,我将您的代码片段包装在足够的样板中以使其编译并运行:

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

使用GCC编译

我在Windows上尽可能简单地编译和链接,这不是太糟糕,因为我安装了Lua for Windows的副本,这恰好让环境变量LUA_DEV指向其安装:

gcc -o q15787892 q15787892.c -mwindows -I"%LUA_DEV%\include" "%LUA_DEV%\lua5.1.dll"

-mwindows标志告诉GCC(特别是链接器ld)将可执行文件标记为完整的Windows GUI程序。如果没有该标志,您将获得一个已经分配了控制台的控制台程序,AllocConsole()将只为提供命令提示符的控制器提供句柄。

结果

有趣的是,print()io.write()的调用都没有产生输出。我在Lua文本中引入了一个语法错误,并注意到它输出到控制台,显示stdout确实被正确重定向。

我在调用FILE *old=stdout;freopen()之前添加了printf("%p %p %p", fp, stdout, oldstdout);。所有三个指针完全相同,表明freopen()没有做出异常的事情。

查看Lua 5.1的print()函数实现的来源,我们发现它只是调用fputs(s,stdout)

那么printf()main()的调用是如何工作的,但使用stdout的类似调用失败了?

解决方案

如果stdout中的main()stdout中的luaB_print()不同,则可能会这样做。

但两者都是全局变量,链接器应该使它们相同,对吧?

嗯,不一定。全局变量stdout是C运行时库的一部分。如果Lua核心链接到与程序不同的C运行时DLL,那么Lua核心和程序实际上可能是指名为stdout不同变量。

使用Dependency Walker进行快速检查表明我的测试可执行文件已与MSVCRT.DLL(MinGW首选的C运行时)相关联,但Lua for Windows的lua5.1.dll与MSVCR80.DLL相关联( Visual Studio 2005中的C运行时。)

这个问题很容易解决。我更改了我的测试用例以链接针对MSVCRT.DLL链接的Lua构建,现在原始代码按预期工作。这是现在在BAT文件中找到的新构建步骤,并假设lua5_1-4_Win32_dll6_lib包含正确构建的Lua核心:

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 .

答案 1 :(得分:0)

另一个可能的原因是发布了luaxx.dll,并且测试项目是版本的版本。所以,luaxx.dll使用msvcrxx.dll,但测试项目使用msvcrxxd.dll - 微软c运行时的版本化版本。