"...Codefoco.Touch.Server.1.0.16/vscode:/vscode.git/clone" did not exist on "d63817e8e71d009b1d817aa95597b48d39f43f28"
Commit dca120aa authored by rostermeier's avatar rostermeier
Browse files

- added functionality to class Lua and LuaDLL for LuaInterfaceDebugger

- Bugfix in ldo.c: structure lua_debug was not initialized completely which caused the .net marshaller to crash

git-svn-id: http://luainterface.googlecode.com/svn/trunk@4 63eb109e-e254-0410-a61e-ed0b8f8614f5
parent 5cc2ec45
...@@ -125,7 +125,8 @@ namespace Lua511 ...@@ -125,7 +125,8 @@ namespace Lua511
*/ */
public delegate int LuaCSFunction(IntPtr luaState); public delegate int LuaCSFunction(IntPtr luaState);
// delegate for lua debug hook callback (by Reinhard Ostermeier)
public delegate void LuaHookFunction(IntPtr luaState, IntPtr luaDebug);
// To fix the strings: // To fix the strings:
...@@ -709,6 +710,100 @@ namespace Lua511 ...@@ -709,6 +710,100 @@ namespace Lua511
return -1; return -1;
} }
// lua debug hook functions added by Reinhard Ostermeier
static int lua_sethook(IntPtr luaState, LuaHookFunction^ func, int mask, int count)
{
IntPtr p;
if (func == nullptr)
{
p = IntPtr::Zero;
}
else
{
p = Marshal::GetFunctionPointerForDelegate(func);
}
return ::lua_sethook(toState, (lua_Hook)p.ToPointer(), mask, count);
}
static int lua_gethookmask(IntPtr luaState)
{
return ::lua_gethookmask(toState);
}
static int lua_gethookcount(IntPtr luaState)
{
return ::lua_gethookcount(toState);
}
static int lua_getstack(IntPtr luaState, int level, IntPtr luaDebug)
{
return ::lua_getstack(toState, level, (lua_Debug*)luaDebug.ToPointer());
}
static int lua_getinfo(IntPtr luaState, String^ what, IntPtr luaDebug)
{
char *cs = (char *) Marshal::StringToHGlobalAnsi(what).ToPointer();
int ret = ::lua_getinfo(toState, cs, (lua_Debug*)luaDebug.ToPointer());
Marshal::FreeHGlobal(IntPtr(cs));
return ret;
}
static String^ lua_getlocal(IntPtr luaState, IntPtr luaDebug, int n)
{
const char* str = ::lua_getlocal(toState, (lua_Debug*)luaDebug.ToPointer(), n);
if (str == NULL)
{
return nullptr;
}
else
{
return gcnew String(str);
}
}
static String^ lua_setlocal(IntPtr luaState, IntPtr luaDebug, int n)
{
const char* str = ::lua_setlocal(toState, (lua_Debug*)luaDebug.ToPointer(), n);
if(str == NULL)
{
return nullptr;
}
else
{
return gcnew String(str);
}
}
static String^ lua_getupvalue(IntPtr luaState, int funcindex, int n)
{
const char* str = ::lua_getupvalue(toState, funcindex, n);
if(str == NULL)
{
return nullptr;
}
else
{
return gcnew String(str);
}
}
static String^ lua_setupvalue(IntPtr luaState, int funcindex, int n)
{
const char* str = ::lua_setupvalue(toState, funcindex, n);
if(str == NULL)
{
return nullptr;
}
else
{
return gcnew String(str);
}
}
// end of lua debug hook functions
private: private:
// Starting with 5.1 the auxlib version of checkudata throws an exception if the type isn't right // Starting with 5.1 the auxlib version of checkudata throws an exception if the type isn't right
......
...@@ -177,7 +177,7 @@ static CallInfo *growCI (lua_State *L) { ...@@ -177,7 +177,7 @@ static CallInfo *growCI (lua_State *L) {
return ++L->ci; return ++L->ci;
} }
// modified by Reinhard Ostermeier to intialize all members of ar (lua_debug)
void luaD_callhook (lua_State *L, int event, int line) { void luaD_callhook (lua_State *L, int event, int line) {
lua_Hook hook = L->hook; lua_Hook hook = L->hook;
if (hook && L->allowhook) { if (hook && L->allowhook) {
...@@ -185,7 +185,15 @@ void luaD_callhook (lua_State *L, int event, int line) { ...@@ -185,7 +185,15 @@ void luaD_callhook (lua_State *L, int event, int line) {
ptrdiff_t ci_top = savestack(L, L->ci->top); ptrdiff_t ci_top = savestack(L, L->ci->top);
lua_Debug ar; lua_Debug ar;
ar.event = event; ar.event = event;
ar.name = NULL;
ar.namewhat = NULL;
ar.what = NULL;
ar.source = NULL;
ar.currentline = line; ar.currentline = line;
ar.nups = 0;
ar.linedefined = 0;
ar.lastlinedefined = 0;
ar.short_src[0] = 0;
if (event == LUA_HOOKTAILRET) if (event == LUA_HOOKTAILRET)
ar.i_ci = 0; /* tail call; no debug information about it */ ar.i_ci = 0; /* tail call; no debug information about it */
else else
......
...@@ -491,6 +491,243 @@ namespace LuaInterface ...@@ -491,6 +491,243 @@ namespace LuaInterface
* Lets go of a previously allocated reference to a table, function * Lets go of a previously allocated reference to a table, function
* or userdata * or userdata
*/ */
#region lua debug functions
/// <summary>
/// lua hook calback delegate
/// </summary>
/// <author>Reinhard Ostermeier</author>
private LuaHookFunction hookCallback = null;
/// <summary>
/// Activates the debug hook
/// </summary>
/// <param name="mask">Mask</param>
/// <param name="count">Count</param>
/// <returns>see lua docs. -1 if hook is already set</returns>
/// <author>Reinhard Ostermeier</author>
public int SetDebugHook(EventMasks mask, int count)
{
if (hookCallback == null)
{
hookCallback = new LuaHookFunction(DebugHookCallback);
return LuaDLL.lua_sethook(luaState, hookCallback, (int)mask, count);
}
return -1;
}
/// <summary>
/// Removes the debug hook
/// </summary>
/// <returns>see lua docs</returns>
/// <author>Reinhard Ostermeier</author>
public int RemoveDebugHook()
{
hookCallback = null;
return LuaDLL.lua_sethook(luaState, null, 0, 0);
}
/// <summary>
/// Gets the hook mask.
/// </summary>
/// <returns>hook mask</returns>
/// <author>Reinhard Ostermeier</author>
public EventMasks GetHookMask()
{
return (EventMasks)LuaDLL.lua_gethookmask(luaState);
}
/// <summary>
/// Gets the hook count
/// </summary>
/// <returns>see lua docs</returns>
/// <author>Reinhard Ostermeier</author>
public int GetHookCount()
{
return LuaDLL.lua_gethookcount(luaState);
}
/// <summary>
/// Gets the stack entry on a given level
/// </summary>
/// <param name="level">level</param>
/// <param name="luaDebug">lua debug structure</param>
/// <returns>Returns true if level was allowed, false if level was invalid.</returns>
/// <author>Reinhard Ostermeier</author>
public bool GetStack(int level, out LuaDebug luaDebug)
{
luaDebug = new LuaDebug();
IntPtr ld = System.Runtime.InteropServices.Marshal.AllocHGlobal(System.Runtime.InteropServices.Marshal.SizeOf(luaDebug));
System.Runtime.InteropServices.Marshal.StructureToPtr(luaDebug, ld, false);
try
{
return LuaDLL.lua_getstack(luaState, level, ld) != 0;
}
finally
{
luaDebug = (LuaDebug)System.Runtime.InteropServices.Marshal.PtrToStructure(ld, typeof(LuaDebug));
System.Runtime.InteropServices.Marshal.FreeHGlobal(ld);
}
}
/// <summary>
/// Gets info (see lua docs)
/// </summary>
/// <param name="what">what (see lua docs)</param>
/// <param name="luaDebug">lua debug structure</param>
/// <returns>see lua docs</returns>
/// <author>Reinhard Ostermeier</author>
public int GetInfo(String what, ref LuaDebug luaDebug)
{
IntPtr ld = System.Runtime.InteropServices.Marshal.AllocHGlobal(System.Runtime.InteropServices.Marshal.SizeOf(luaDebug));
System.Runtime.InteropServices.Marshal.StructureToPtr(luaDebug, ld, false);
try
{
return LuaDLL.lua_getinfo(luaState, what, ld);
}
finally
{
luaDebug = (LuaDebug)System.Runtime.InteropServices.Marshal.PtrToStructure(ld, typeof(LuaDebug));
System.Runtime.InteropServices.Marshal.FreeHGlobal(ld);
}
}
/// <summary>
/// Gets local (see lua docs)
/// </summary>
/// <param name="luaDebug">lua debug structure</param>
/// <param name="n">see lua docs</param>
/// <returns>see lua docs</returns>
/// <author>Reinhard Ostermeier</author>
public String GetLocal(LuaDebug luaDebug, int n)
{
IntPtr ld = System.Runtime.InteropServices.Marshal.AllocHGlobal(System.Runtime.InteropServices.Marshal.SizeOf(luaDebug));
System.Runtime.InteropServices.Marshal.StructureToPtr(luaDebug, ld, false);
try
{
return LuaDLL.lua_getlocal(luaState, ld, n);
}
finally
{
System.Runtime.InteropServices.Marshal.FreeHGlobal(ld);
}
}
/// <summary>
/// Sets local (see lua docs)
/// </summary>
/// <param name="luaDebug">lua debug structure</param>
/// <param name="n">see lua docs</param>
/// <returns>see lua docs</returns>
/// <author>Reinhard Ostermeier</author>
public String SetLocal(LuaDebug luaDebug, int n)
{
IntPtr ld = System.Runtime.InteropServices.Marshal.AllocHGlobal(System.Runtime.InteropServices.Marshal.SizeOf(luaDebug));
System.Runtime.InteropServices.Marshal.StructureToPtr(luaDebug, ld, false);
try
{
return LuaDLL.lua_setlocal(luaState, ld, n);
}
finally
{
System.Runtime.InteropServices.Marshal.FreeHGlobal(ld);
}
}
/// <summary>
/// Gets up value (see lua docs)
/// </summary>
/// <param name="funcindex">see lua docs</param>
/// <param name="n">see lua docs</param>
/// <returns>see lua docs</returns>
/// <author>Reinhard Ostermeier</author>
public String GetUpValue(int funcindex, int n)
{
return LuaDLL.lua_getupvalue(luaState, funcindex, n);
}
/// <summary>
/// Sets up value (see lua docs)
/// </summary>
/// <param name="funcindex">see lua docs</param>
/// <param name="n">see lua docs</param>
/// <returns>see lua docs</returns>
/// <author>Reinhard Ostermeier</author>
public String SetUpValue(int funcindex, int n)
{
return LuaDLL.lua_setupvalue(luaState, funcindex, n);
}
/// <summary>
/// Delegate that is called on lua hook callback
/// </summary>
/// <param name="luaState">lua state</param>
/// <param name="luaDebug">Pointer to LuaDebug (lua_debug) structure</param>
/// <author>Reinhard Ostermeier</author>
private void DebugHookCallback(IntPtr luaState, IntPtr luaDebug)
{
try
{
LuaDebug ld = (LuaDebug)System.Runtime.InteropServices.Marshal.PtrToStructure(luaDebug, typeof(LuaDebug));
EventHandler<DebugHookEventArgs> temp = DebugHook;
if (temp != null)
{
temp(this, new DebugHookEventArgs(ld));
}
}
catch (Exception ex)
{
OnHookException(new HookExceptionEventArgs(ex));
}
}
/// <summary>
/// Event that is raised when an exception occures during a hook call.
/// </summary>
/// <author>Reinhard Ostermeier</author>
public event EventHandler<HookExceptionEventArgs> HookException;
private void OnHookException(HookExceptionEventArgs e)
{
EventHandler<HookExceptionEventArgs> temp = HookException;
if (temp != null)
{
temp(this, e);
}
}
/// <summary>
/// Event when lua hook callback is called
/// </summary>
/// <remarks>
/// Is only raised if SetDebugHook is called before.
/// </remarks>
/// <author>Reinhard Ostermeier</author>
public event EventHandler<DebugHookEventArgs> DebugHook;
/// <summary>
/// Pops a value from the lua stack.
/// </summary>
/// <returns>Returns the top value from the lua stack.</returns>
/// <author>Reinhard Ostermeier</author>
public object Pop()
{
int top = Lua511.LuaDLL.lua_gettop(luaState);
return translator.popValues(luaState, top - 1)[0];
}
/// <summary>
/// Pushes a value onto the lua stack.
/// </summary>
/// <param name="value">Value to push.</param>
/// <author>Reinhard Ostermeier</author>
public void Push(object value)
{
translator.push(luaState, value);
}
#endregion
internal void dispose(int reference) internal void dispose(int reference)
{ {
if (luaState != IntPtr.Zero) //Fix submitted by Qingrui Li if (luaState != IntPtr.Zero) //Fix submitted by Qingrui Li
...@@ -614,5 +851,99 @@ namespace LuaInterface ...@@ -614,5 +851,99 @@ namespace LuaInterface
} }
#endregion #endregion
} }
/// <summary>
/// Event codes for lua hook function
/// </summary>
/// <remarks>
/// Do not change any of the values because they must match the lua values
/// </remarks>
/// <author>Reinhard Ostermeier</author>
public enum EventCodes
{
LUA_HOOKCALL = 0,
LUA_HOOKRET = 1,
LUA_HOOKLINE = 2,
LUA_HOOKCOUNT = 3,
LUA_HOOKTAILRET = 4,
}
/// <summary>
/// Event masks for lua hook callback
/// </summary>
/// <remarks>
/// Do not change any of the values because they must match the lua values
/// </remarks>
/// <author>Reinhard Ostermeier</author>
[Flags]
public enum EventMasks
{
LUA_MASKCALL = (1 << EventCodes.LUA_HOOKCALL),
LUA_MASKRET = (1 << EventCodes.LUA_HOOKRET),
LUA_MASKLINE = (1 << EventCodes.LUA_HOOKLINE),
LUA_MASKCOUNT = (1 << EventCodes.LUA_HOOKCOUNT),
LUA_MASKALL = Int32.MaxValue,
}
/// <summary>
/// Structure for lua debug information
/// </summary>
/// <remarks>
/// Do not change this struct because it must match the lua structure lua_debug
/// </remarks>
/// <author>Reinhard Ostermeier</author>
[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
public struct LuaDebug
{
public EventCodes eventCode;
[System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPStr)]
public String name;
[System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPStr)]
public String namewhat;
[System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPStr)]
public String what;
[System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPStr)]
public String source;
public int currentline;
public int nups;
public int linedefined;
public int lastlinedefined;
[System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst = 60/*LUA_IDSIZE*/)]
public String shortsrc;
public int i_ci;
}
/// <summary>
/// Event args for hook callback event
/// </summary>
/// <author>Reinhard Ostermeier</author>
public class DebugHookEventArgs : EventArgs
{
private readonly LuaDebug luaDebug;
public DebugHookEventArgs(LuaDebug luaDebug)
{
this.luaDebug = luaDebug;
}
public LuaDebug LuaDebug
{
get { return luaDebug; }
}
}
public class HookExceptionEventArgs : EventArgs
{
private readonly Exception m_Exception;
public Exception Exception
{
get { return m_Exception; }
}
public HookExceptionEventArgs(Exception ex)
{
m_Exception = ex;
}
}
} }
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment