我的代码看起来像那样(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错误)
答案 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
}
我在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运行时的版本化版本。