使用Visual Studio调试模式下,嵌入式Lua中的“print”无法正常工作

3
我正在使用Luainterface 2.0.3在c#应用程序中嵌入Lua。除了在Visual Studio的调试模式下,Lua的打印功能无法写入控制台(也不会输出)之外,一切都运行良好。
using System;
using LuaInterface;

namespace Lua1 {
    class Program {
       static void Main(string[] args) {
          Lua lua = new Lua();
          lua.DoString("print 'Hello from Lua!'");
       }
    }
}    

在非调试模式下运行时,print功能正常。

我是否遗漏了什么?

谢谢!

4个回答

8

很不幸,你可能面临着print()函数中已知的缺陷,这个函数实际上是用于快速和简单的调试控制台提示信息,缺少一些必要的灵活性。

基本库函数print()lbaselib.c中的luaB_print()实现,显式地使用C运行时的stdout流作为其目标。由于它在实现中明确引用全局变量stdout,因此唯一重定向它的方法是使该文件句柄被重定向。在C程序中,可以通过调用freopen(stdout,...)来完成。不幸的是,Lua中没有一个库函数能够做到这一点。

io 库的实现在 liolib.c 中。它使用函数环境来保存打开文件描述符的表,在初始化期间,它创建了名为 io.stdinio.stdoutio.stderrfile 对象以表示三个标准描述符。它还提供了名为 io.outputio.input 的函数,以允许修改这两个描述符指向任何打开的 file 对象(或者如果传递了文件名,则指向新打开的文件)。但是,这些函数只会更改函数环境表,并不会调用 freopen() 来修改 C 运行时的 FILE 值表。
我不知道 LuaInterface 如何尝试处理标准 C 运行时对 stdout 的理解。很可能由于它可能利用某些 .NET 特性来捕获从被调试模块输出的内容,因此 stdout 在 VS 调试器中可能没有连接到任何有用的东西,而且这在任何情况下都可能与 C 不太兼容。

话虽如此,替换标准的print函数很容易。只需使用LuaInterface的现有功能编写一个名为print的全局函数,该函数在每个参数上调用tostring()并将其传递给任何.NET东西作为标准输出设备。


3
我没有使用过LuaInterface,所以无法确定,但您可能想尝试手动调用。
io.output(io.stdout)

查看《Lua编程》第21.1章,他们解释了如何通过设置io.output来重定向print的输出位置。另请参阅IO库教程

然而,我不确定这是否真正解决了问题,因为我在Google Code上的LuaInterface源代码中找不到任何与设置io.output有关的内容。


2

以下是如何使用LuaDLL类的代码示例,该类用于在LuaInterface中重定向lua打印函数:

// See http://medek.wordpress.com/2009/02/03/wrapping-lua-errors-and-print-function/
static int LuaPrint(IntPtr L)
{
  int nArgs = LuaDLL.lua_gettop(L);
  LuaDLL.lua_getglobal(L, "tostring");
  string ret = ""; //this is where we will dump the output
  //make sure you start at 1 *NOT* 0
  for(int i = 1; i <= nArgs; i++)
  {
      LuaDLL.lua_pushvalue(L, -1);
      LuaDLL.lua_pushvalue(L, i);
      LuaDLL.lua_call(L, 1, 1);
      string s = LuaDLL.lua_tostring(L, -1);
      if(s == null)
          return LuaDLL.luaL_error(L, "\"tostring\" must return a string to \"print\"");
      if(i > 1) ret += "\t";
      ret += s;
      LuaDLL.lua_pop(L, 1);
  };
  //Send it wherever
  Console.Out.WriteLine(ret);
  return 0;
}

C#中Lua的初始化如下:
IntPtr luaState = LuaDLL.luaL_newstate();
LuaDLL.luaL_openlibs(luaState);
LuaDLL.lua_newtable(luaState);
LuaDLL.lua_setglobal(luaState, "luanet");
Lua l = new Lua(luaState.ToInt64());
LuaDLL.lua_register(luaState, "print", new LuaCSFunction(LuaPrint));

1

替换文件"lua/etc/luavs.bat"中的第七行

@set MYCOMPILE=cl /nologo /MD /O2 /W3 /c /D_CRT_SECURE_NO_DEPRECATE

使用

@set MYCOMPILE=cl /nologo /MDd /Od /W3 /c /D_CRT_SECURE_NO_DEPRECATE

并使用MSVCRT的调试版本重新编译lua。之后,您的输出将按预期重定向。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接