2009-09-23 106 views
3

我正在使用Luainterface 2.0.3將Lua嵌入到c#應用程序中。嵌入式Lua「print」不能在Visual Studio的調試模式下工作

一切工作正常,除了在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!'"); 
     } 
    } 
}  

在非調試模式下運行它,打印工作正常。

我錯過了什麼嗎?

謝謝!

回答

8

不幸的是,您可能已經遇到print()函數中的一個已知缺陷,該函數實際上是用於在控制檯提示符下進行快速和骯髒的調試,並且缺少一些必要的靈活性。

luaB_print() in lbaselib.c實現的基本庫函數print()明確使用C運行時的stdout流作爲其目標。由於它在其實現中顯式引用了全局變量stdout,因此重定向它的唯一方法是使該文件句柄被重定向。在C程序中可以通過調用freopen(stdout,...)來完成。不幸的是,Lua中沒有庫存函數可以做到這一點。

io庫在liolib.c中實現。它使用功能環境來保存打開文件描述符的表格,並且在其初始化期間,它爲三個標準描述符創建名稱爲io.stdinio.stdoutio.stderr的對象file。它還提供名爲io.outputio.input的函數,允許修改這兩個描述符以指向任何打開的對象(如果傳遞文件名,則爲新打開的文件)。但是,這些函數只會更改函數環境表,並且不要調用freopen()來修改C運行時的FILE值表。

我不知道LuaInterface如何試圖處理標準C運行時的想法stdout。很可能stdout沒有連接到VS調試器中任何有用的東西,因爲它可能利用了某些.NET功能來捕獲正在調試的模塊的輸出,在任何情況下都可能與C不兼容。

這就是說,很容易替換標準的print函數。只需使用LuaInterface的現有功能編寫一個名爲print的全局函數,該函數在每個參數上調用tostring()並將它傳遞給任何.NET事物是標準輸出設備。

2

我沒有用過LuaInterface,所以我不能肯定地說,但你可能想嘗試手動調用

io.output(io.stdout) 

看着Programming in Lua ch 21.1,他們解釋如何重定向哪裏print的輸出通過設置io.output。另請參閱IO Library Tutorial

但是,我不確定這是否會真正解決問題,因爲我找不到任何與the LuaInterface source on Google Code中設置的io.output相關的任何內容。

1

文件 「LUA的/ etc/luavs.bat」

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

替換線7

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

與MSVCRT的調試版本重新編譯LUA。之後,您的輸出將按預期重定向。

2

下面一個代碼示例如何使用在LuaInterface使用的LuaDLL類重定向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; 
} 

LUA的C#中的初始化是這樣的:

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)); 
相關問題