Embedded Lua “print” not working in debug mode fro

2019-02-19 00:29发布

问题:

I am using Luainterface 2.0.3 to embed Lua in a c# application.

Everything is working fine, except in visual Studio's debug mode, the Lua's print function does not get written to the console (nor to Output).

using System;
using LuaInterface;

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

Running it in non debugging mode, print is working fine.

Am I missing something?

Thanks!

回答1:

Unfortunately, you are probably up against a known deficiency in the print() function, which is really intended for quick and dirty debugging at a console prompt, and is missing some necessary flexibility.

The base library function print() implemented by luaB_print() in lbaselib.c explicitly uses the C runtime's stdout stream as its destination. Since it refers to the global variable stdout explicitly in its implementation, the only way to redirect it is to cause that file handle to be redirected. In a C program that can be done by calling freopen(stdout,...). Unfortunately, there isn't a stock library function in Lua that can do that.

The io library is implemented in liolib.c. It uses the function environment to hold a table of open file descriptors, and during its initialization it creates file objects named io.stdin, io.stdout and io.stderr for the three standard descriptors. It also provides functions named io.output and io.input to allow those two descriptors to be modified to point to any open file object (or a newly opened file if a file name is passed). However, those functions only change the function environment table and do not call freopen() to modify the C runtime's table of FILE values.

I have no idea how LuaInterface attempts to treat the standard C runtime's idea of stdout. It may very well be that stdout is not connected to anything useful in the VS debugger because it probably takes advantage of some .NET feature to capture output from the module being debugged that may not be all that compatible with C in any case.

That said, it is easy to replace the standard print function. Just use existing features of LuaInterface to write a global function named print that calls tostring() on each argument and passes it to the whatever .NET things is the standard output device.



回答2:

I haven't used LuaInterface, so I can't say for sure, but you might want to try manually calling

io.output(io.stdout)

Looking at Programming in Lua ch 21.1, they explain how you can redirect where print's output goes by setting io.output. See also the IO Library Tutorial.

I'm unsure whether this will actually solve the problem, however, as I can't find anything related to io.output being set in the LuaInterface source on Google Code.



回答3:

Here a code sample how to use the LuaDLL class used in the LuaInterface to redirect the lua print function:

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

The initialization of lua in C# look like:

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


回答4:

Replace line 7 in file "lua/etc/luavs.bat"

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

with

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

and recompile lua with the debug version of MSVCRT. After that your output will be redirected as expected.