从Visual Studio调试模式中无法使用嵌入式Lua中的"print"函数。

我正在使用Luainterface 2.0.3将Lua嵌入到C#应用程序中。

一切都正常工作,但是在Visual Studio的调试模式下,Lua的_print_函数不会写入控制台(也不会写入输出)。

using System;
using LuaInterface;

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

在非调试模式下运行,_print_正常工作。

我错过了什么吗?

谢谢!

原文链接 https://stackoverflow.com/questions/1466064

点赞
stackoverflow用户126042
stackoverflow用户126042

我没有使用过 LuaInterface,所以不能确定,但是你可能想尝试手动调用

io.output(io.stdout)

查看《Lua 程序设计》第21.1章,它们解释了如何通过设置 io.output 来重定向 print 的输出位置。还可以参考IO库教程

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

2009-09-23 16:29:21
stackoverflow用户68204
stackoverflow用户68204

很不幸,你可能已经遇到了 print() 函数中众所周知的缺陷,这个函数实际上是用来快速粗略地调试控制台命令行的,并且缺少一些必要的灵活性。

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

io 库是在 liolib.c 中实现的。它使用函数环境来存储已打开文件描述符的表,在初始化期间,它为三个标准描述符创建了名为 io.stdinio.stdoutio.stderrfile 对象。它还提供了名为 io.inputio.output 的函数,以允许这两个描述符被修改以指向任何打开的 file 对象(或者如果传递了文件名,则指向一个新打开的文件)。然而,这些函数只会改变函数环境表,并不会调用 freopen() 来修改 C 运行时的 FILE 值表。

我不知道 LuaInterface 是如何处理标准 C 运行时中的 stdout 概念的。很可能,stdout 没有连接到 VS 调试器中的任何有用内容,因为它可能利用了某些 .NET 特性来捕获从调试的模块中产生的输出,而这些特性可能在任何情况下都与 C 不太兼容。

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

2009-09-23 22:09:29
stackoverflow用户387987
stackoverflow用户387987

将文件 "lua/etc/luavs.bat" 中的第 7 行替换为:

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

然后使用 MSVCRT 的 Debug 版本重新编译 lua。之后你的输出将被正确地重定向。

2010-07-09 17:36:28
stackoverflow用户142860
stackoverflow用户142860

下面是如何使用 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));
2010-12-01 02:52:19