嵌入式Lua不会打印到分配的控制台 [英] Embedded Lua does not print to allocated console

查看:322
本文介绍了嵌入式Lua不会打印到分配的控制台的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

我无法获得Lua输出,而正常的printf工作也打印)

I can't get Lua output, while normal printf works (Lua errors are also printed)

推荐答案

TL; DR:程序正在使用多个版本的C运行时库。不要这样做。

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.

从表面上看,代码你应该工作。而且,如果建立和链接在这里,我可以使它的工作。作为参考,我正在建设与MingW GCC 4.7.2,对于32位Windows,在Win7 Pro。但我相信,任何针对Windows的编译器都可能发生潜在的问题。

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
}



使用GCC编译



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

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

-mwindows 标志告诉GCC(特别是链接器 ld )将可执行文件标记为完整的Windows GUI程序。没有这个标志,你得到一个控制台程序已经分配了一个控制台,AllocConsole()将简单地提供句柄给持有命令提示符的句柄。

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.

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

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.

在调用 freopen()和<$ c之前,我添加了 FILE * old = stdout; $ c> printf(%p%p%p,fp,stdout,oldstdout); 之后。所有三个指针都是完全相等的,表明 freopen()没有做什么不寻常的事。

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.

来源到Lua 5.1的 打印( ) 函数,我们发现它只是调用 fputs(s,stdout)

Looking in the sources to Lua 5.1's implementation of the print() function we find that it simply calls fputs(s,stdout).

那么如何从 main()调用 printf()

So how is it possible that a call to printf() from main() works, but a similar call using stdout fails?

中的 stdout 可能不一样 c>

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?

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

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.

使用 Dependency Walker 显示我的测试可执行文件链接到MSVCRT.DLL(MinGW喜欢的C运行时),但来自Lua for Windows的 lua5.1.dll MSVCR80.DLL(Visual Studio 2005中的C运行时)。

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).

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

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 .

这篇关于嵌入式Lua不会打印到分配的控制台的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆