933 lines
23 KiB
C++
933 lines
23 KiB
C++
|
|
using namespace System;
|
|
using namespace System::Runtime::InteropServices;
|
|
using namespace System::Reflection;
|
|
using namespace System::Collections;
|
|
using namespace System::Text;
|
|
using namespace System::Security;
|
|
|
|
// #include <vcclr.h>
|
|
// #define _WINNT_
|
|
// #include <WinDef.h>
|
|
#include <vcclr.h>
|
|
// #include <atlstr.h>
|
|
#include <stdio.h>
|
|
#using <mscorlib.dll>
|
|
#include <string.h>
|
|
|
|
#define LUA_BUILD_AS_DLL
|
|
#define LUA_LIB
|
|
#define LUA_CORE
|
|
#define lua_c
|
|
#define luac_c
|
|
#define loslib_c
|
|
|
|
extern "C"
|
|
{
|
|
#include "lua.h"
|
|
#include "lualib.h"
|
|
#include "lauxlib.h"
|
|
}
|
|
|
|
// Not sure of the purpose of this, but I'm keeping it -kevinh
|
|
static int tag = 0;
|
|
|
|
namespace Lua511
|
|
{
|
|
|
|
|
|
#if 1
|
|
#undef LUA_TNONE
|
|
#undef LUA_TNIL
|
|
#undef LUA_TNUMBER
|
|
#undef LUA_TSTRING
|
|
#undef LUA_TBOOLEAN
|
|
#undef LUA_TTABLE
|
|
#undef LUA_TFUNCTION
|
|
#undef LUA_TUSERDATA
|
|
#undef LUA_TLIGHTUSERDATA
|
|
|
|
/*
|
|
* Lua types for the API, returned by lua_type function
|
|
*/
|
|
public enum class LuaTypes
|
|
{
|
|
LUA_TNONE=-1,
|
|
LUA_TNIL=0,
|
|
LUA_TNUMBER=3,
|
|
LUA_TSTRING=4,
|
|
LUA_TBOOLEAN=1,
|
|
LUA_TTABLE=5,
|
|
LUA_TFUNCTION=6,
|
|
LUA_TUSERDATA=7,
|
|
LUA_TLIGHTUSERDATA=2
|
|
};
|
|
|
|
#endif
|
|
|
|
#if 1
|
|
#undef LUA_GCSTOP
|
|
#undef LUA_GCRESTART
|
|
#undef LUA_GCCOLLECT
|
|
#undef LUA_GCCOUNT
|
|
#undef LUA_GCCOUNTB
|
|
#undef LUA_GCSTEP
|
|
#undef LUA_GCSETPAUSE
|
|
#undef LUA_GCSETSTEPMUL
|
|
|
|
/*
|
|
* Lua Garbage Collector options (param "what")
|
|
*/
|
|
public enum class LuaGCOptions
|
|
{
|
|
LUA_GCSTOP = 0,
|
|
LUA_GCRESTART = 1,
|
|
LUA_GCCOLLECT = 2,
|
|
LUA_GCCOUNT = 3,
|
|
LUA_GCCOUNTB = 4,
|
|
LUA_GCSTEP = 5,
|
|
LUA_GCSETPAUSE = 6,
|
|
LUA_GCSETSTEPMUL = 7,
|
|
};
|
|
#endif
|
|
|
|
#undef LUA_REGISTRYINDEX
|
|
#undef LUA_ENVIRONINDEX
|
|
#undef LUA_GLOBALSINDEX
|
|
|
|
/*
|
|
* Special stack indexes
|
|
*/
|
|
public enum class LuaIndexes
|
|
{
|
|
LUA_REGISTRYINDEX=-10000,
|
|
LUA_ENVIRONINDEX=-10001,
|
|
LUA_GLOBALSINDEX=-10002
|
|
};
|
|
|
|
|
|
#if 0
|
|
/*
|
|
* Structure used by the chunk reader
|
|
*/
|
|
// [ StructLayout( LayoutKind.Sequential )]
|
|
public ref struct ReaderInfo
|
|
{
|
|
public String^ chunkData;
|
|
public bool finished;
|
|
};
|
|
|
|
|
|
/*
|
|
* Delegate for chunk readers used with lua_load
|
|
*/
|
|
public delegate String^ LuaChunkReader(IntPtr luaState, ReaderInfo ^data, uint size);
|
|
#endif
|
|
|
|
/*
|
|
* Delegate for functions passed to Lua as function pointers
|
|
*/
|
|
[System::Runtime::InteropServices::UnmanagedFunctionPointer(CallingConvention::Cdecl)]
|
|
public delegate int LuaCSFunction(IntPtr luaState);
|
|
|
|
// delegate for lua debug hook callback (by Reinhard Ostermeier)
|
|
[System::Runtime::InteropServices::UnmanagedFunctionPointer(CallingConvention::Cdecl)]
|
|
public delegate void LuaHookFunction(IntPtr luaState, IntPtr luaDebug);
|
|
|
|
|
|
// To fix the strings:
|
|
// http://support.microsoft.com/kb/311259
|
|
|
|
public ref class LuaDLL
|
|
{
|
|
// steffenj: BEGIN additional Lua API functions new in Lua 5.1
|
|
public:
|
|
|
|
#define toState ((lua_State *) luaState.ToPointer())
|
|
|
|
static int lua_gc(IntPtr luaState, LuaGCOptions what, int data)
|
|
{
|
|
return ::lua_gc(toState, (int) what, data);
|
|
}
|
|
|
|
static String^ lua_typename(IntPtr luaState, LuaTypes type)
|
|
{
|
|
return gcnew String(::lua_typename(toState, (int) type));
|
|
}
|
|
|
|
#undef luaL_typename
|
|
|
|
static String^ luaL_typename(IntPtr luaState, int stackPos)
|
|
{
|
|
return lua_typename(luaState, lua_type(luaState, stackPos));
|
|
}
|
|
|
|
static void luaL_error(IntPtr luaState, String^ message)
|
|
{
|
|
char *cs = (char *) Marshal::StringToHGlobalAnsi(message).ToPointer();
|
|
|
|
::luaL_error(toState, cs);
|
|
Marshal::FreeHGlobal(IntPtr(cs));
|
|
}
|
|
|
|
static void luaL_where(IntPtr luaState, int level)
|
|
{
|
|
::luaL_where(toState, level);
|
|
}
|
|
|
|
|
|
// Not yet wrapped
|
|
// static String^ luaL_gsub(IntPtr luaState, String^ str, String^ pattern, String^ replacement);
|
|
|
|
#if 0
|
|
// the functions below are still untested
|
|
static void lua_getfenv(IntPtr luaState, int stackPos);
|
|
static int lua_isfunction(IntPtr luaState, int stackPos);
|
|
static int lua_islightuserdata(IntPtr luaState, int stackPos);
|
|
static int lua_istable(IntPtr luaState, int stackPos);
|
|
static int lua_isuserdata(IntPtr luaState, int stackPos);
|
|
static int lua_lessthan(IntPtr luaState, int stackPos1, int stackPos2);
|
|
static int lua_rawequal(IntPtr luaState, int stackPos1, int stackPos2);
|
|
static int lua_setfenv(IntPtr luaState, int stackPos);
|
|
static void lua_setfield(IntPtr luaState, int stackPos, String^ name);
|
|
static int luaL_callmeta(IntPtr luaState, int stackPos, String^ name);
|
|
// steffenj: END additional Lua API functions new in Lua 5.1
|
|
#endif
|
|
|
|
// steffenj: BEGIN Lua 5.1.1 API change (lua_open replaced by luaL_newstate)
|
|
static IntPtr luaL_newstate()
|
|
{
|
|
return IntPtr(::luaL_newstate());
|
|
}
|
|
|
|
static void lua_close(IntPtr luaState)
|
|
{
|
|
::lua_close(toState);
|
|
}
|
|
|
|
// steffenj: BEGIN Lua 5.1.1 API change (new function luaL_openlibs)
|
|
static void luaL_openlibs(IntPtr luaState)
|
|
{
|
|
::luaL_openlibs(toState);
|
|
}
|
|
|
|
// Not yet wrapped
|
|
// static int lua_objlen(IntPtr luaState, int stackPos);
|
|
|
|
// steffenj: END Lua 5.1.1 API change (lua_strlen is now lua_objlen)
|
|
// steffenj: BEGIN Lua 5.1.1 API change (lua_doString^ is now a macro luaL_dostring)
|
|
static int luaL_loadstring(IntPtr luaState, String^ chunk)
|
|
{
|
|
char *cs = (char *) Marshal::StringToHGlobalAnsi(chunk).ToPointer();
|
|
|
|
int result = ::luaL_loadstring(toState, cs);
|
|
Marshal::FreeHGlobal(IntPtr(cs));
|
|
|
|
return result;
|
|
}
|
|
|
|
#undef luaL_dostring
|
|
|
|
static int luaL_dostring(IntPtr luaState, String^ chunk)
|
|
{
|
|
int result = luaL_loadstring(luaState, chunk);
|
|
if (result != 0)
|
|
return result;
|
|
|
|
return lua_pcall(luaState, 0, -1, 0);
|
|
}
|
|
|
|
/// <summary>DEPRECATED - use luaL_dostring(IntPtr luaState, string chunk) instead!</summary>
|
|
static int lua_dostring(IntPtr luaState, String^ chunk)
|
|
{
|
|
return luaL_dostring(luaState, chunk);
|
|
}
|
|
|
|
// steffenj: END Lua 5.1.1 API change (lua_dostring is now a macro luaL_dostring)
|
|
// steffenj: BEGIN Lua 5.1.1 API change (lua_newtable is gone, lua_createtable is new)
|
|
static void lua_createtable(IntPtr luaState, int narr, int nrec)
|
|
{
|
|
::lua_createtable(toState, narr, nrec);
|
|
}
|
|
|
|
#undef lua_newtable
|
|
|
|
static void lua_newtable(IntPtr luaState)
|
|
{
|
|
lua_createtable(luaState, 0, 0);
|
|
}
|
|
|
|
#undef luaL_dofile
|
|
|
|
// steffenj: END Lua 5.1.1 API change (lua_newtable is gone, lua_createtable is new)
|
|
// steffenj: BEGIN Lua 5.1.1 API change (lua_dofile now in LuaLib as luaL_dofile macro)
|
|
static int luaL_dofile(IntPtr luaState, String^ fileName)
|
|
{
|
|
char *cs = (char *) Marshal::StringToHGlobalAnsi(fileName).ToPointer();
|
|
|
|
int result = ::luaL_loadfile(toState, cs);
|
|
|
|
//CP: Free filename string before return to ensure a file that isnt found still has the string freed (submitted by paul moore)
|
|
//link: http://luaforge.net/forum/forum.php?thread_id=2825&forum_id=145
|
|
Marshal::FreeHGlobal(IntPtr(cs));
|
|
|
|
if (result != 0)
|
|
return result;
|
|
|
|
return ::lua_pcall(toState, 0, -1, 0);
|
|
}
|
|
|
|
#undef lua_getglobal
|
|
|
|
// steffenj: END Lua 5.1.1 API change (lua_dofile now in LuaLib as luaL_dofile)
|
|
static void lua_getglobal(IntPtr luaState, String^ name)
|
|
{
|
|
lua_pushstring(luaState, name);
|
|
::lua_gettable(toState, (int) LuaIndexes::LUA_GLOBALSINDEX);
|
|
}
|
|
|
|
#undef lua_setglobal
|
|
|
|
static void lua_setglobal(IntPtr luaState, String^ name)
|
|
{
|
|
lua_pushstring(luaState,name);
|
|
lua_insert(luaState,-2);
|
|
lua_settable(luaState, (int) LuaIndexes::LUA_GLOBALSINDEX);
|
|
}
|
|
|
|
static void lua_settop(IntPtr luaState, int newTop)
|
|
{
|
|
::lua_settop(toState, newTop);
|
|
}
|
|
|
|
|
|
#undef lua_pop
|
|
|
|
static void lua_pop(IntPtr luaState, int amount)
|
|
{
|
|
lua_settop(luaState, -(amount) - 1);
|
|
}
|
|
|
|
static void lua_insert(IntPtr luaState, int newTop)
|
|
{
|
|
::lua_insert(toState, newTop);
|
|
}
|
|
|
|
static void lua_remove(IntPtr luaState, int index)
|
|
{
|
|
::lua_remove(toState, index);
|
|
}
|
|
|
|
static void lua_gettable(IntPtr luaState, int index)
|
|
{
|
|
::lua_gettable(toState, index);
|
|
}
|
|
|
|
|
|
static void lua_rawget(IntPtr luaState, int index)
|
|
{
|
|
::lua_rawget(toState, index);
|
|
}
|
|
|
|
|
|
static void lua_settable(IntPtr luaState, int index)
|
|
{
|
|
::lua_settable(toState, index);
|
|
}
|
|
|
|
|
|
static void lua_rawset(IntPtr luaState, int index)
|
|
{
|
|
::lua_rawset(toState, index);
|
|
}
|
|
|
|
static IntPtr lua_newthread(IntPtr luaState)
|
|
{
|
|
return IntPtr(::lua_newthread(toState));
|
|
}
|
|
|
|
static int lua_resume(IntPtr luaState, int narg)
|
|
{
|
|
return ::lua_resume(toState, narg);
|
|
}
|
|
|
|
static int lua_yield(IntPtr luaState, int nresults)
|
|
{
|
|
return ::lua_yield(toState, nresults);
|
|
}
|
|
|
|
|
|
static void lua_setmetatable(IntPtr luaState, int objIndex)
|
|
{
|
|
::lua_setmetatable(toState, objIndex);
|
|
}
|
|
|
|
|
|
static int lua_getmetatable(IntPtr luaState, int objIndex)
|
|
{
|
|
return ::lua_getmetatable(toState, objIndex);
|
|
}
|
|
|
|
|
|
static int lua_equal(IntPtr luaState, int index1, int index2)
|
|
{
|
|
return ::lua_equal(toState, index1, index2);
|
|
}
|
|
|
|
|
|
static void lua_pushvalue(IntPtr luaState, int index)
|
|
{
|
|
::lua_pushvalue(toState, index);
|
|
}
|
|
|
|
|
|
static void lua_replace(IntPtr luaState, int index)
|
|
{
|
|
::lua_replace(toState, index);
|
|
}
|
|
|
|
static int lua_gettop(IntPtr luaState)
|
|
{
|
|
return ::lua_gettop(toState);
|
|
}
|
|
|
|
|
|
static LuaTypes lua_type(IntPtr luaState, int index)
|
|
{
|
|
return (LuaTypes) ::lua_type(toState, index);
|
|
}
|
|
|
|
#undef lua_isnil
|
|
|
|
static bool lua_isnil(IntPtr luaState, int index)
|
|
{
|
|
return lua_type(luaState,index)==LuaTypes::LUA_TNIL;
|
|
}
|
|
|
|
static bool lua_isnumber(IntPtr luaState, int index)
|
|
{
|
|
return lua_type(luaState,index)==LuaTypes::LUA_TNUMBER;
|
|
}
|
|
|
|
#undef lua_isboolean
|
|
|
|
static bool lua_isboolean(IntPtr luaState, int index)
|
|
{
|
|
return lua_type(luaState,index)==LuaTypes::LUA_TBOOLEAN;
|
|
}
|
|
|
|
static int luaL_ref(IntPtr luaState, int registryIndex)
|
|
{
|
|
return ::luaL_ref(toState, registryIndex);
|
|
}
|
|
|
|
#undef lua_ref
|
|
|
|
static int lua_ref(IntPtr luaState, int lockRef)
|
|
{
|
|
if(lockRef!=0)
|
|
{
|
|
return luaL_ref(luaState, (int) LuaIndexes::LUA_REGISTRYINDEX);
|
|
}
|
|
else return 0;
|
|
}
|
|
|
|
static void lua_rawgeti(IntPtr luaState, int tableIndex, int index)
|
|
{
|
|
::lua_rawgeti(toState, tableIndex, index);
|
|
}
|
|
|
|
static void lua_rawseti(IntPtr luaState, int tableIndex, int index)
|
|
{
|
|
::lua_rawseti(toState, tableIndex, index);
|
|
}
|
|
|
|
|
|
static IntPtr lua_newuserdata(IntPtr luaState, int size)
|
|
{
|
|
return IntPtr(::lua_newuserdata(toState, size));
|
|
}
|
|
|
|
|
|
static IntPtr lua_touserdata(IntPtr luaState, int index)
|
|
{
|
|
return IntPtr(::lua_touserdata(toState, index));
|
|
}
|
|
|
|
#undef lua_getref
|
|
|
|
static void lua_getref(IntPtr luaState, int reference)
|
|
{
|
|
lua_rawgeti(luaState, (int) LuaIndexes::LUA_REGISTRYINDEX,reference);
|
|
}
|
|
|
|
// Unwrapped
|
|
// static void luaL_unref(IntPtr luaState, int registryIndex, int reference);
|
|
|
|
#undef lua_unref
|
|
|
|
static void lua_unref(IntPtr luaState, int reference)
|
|
{
|
|
::luaL_unref(toState, (int) LuaIndexes::LUA_REGISTRYINDEX,reference);
|
|
}
|
|
|
|
static bool lua_isstring(IntPtr luaState, int index)
|
|
{
|
|
return ::lua_isstring(toState, index) != 0;
|
|
}
|
|
|
|
|
|
static bool lua_iscfunction(IntPtr luaState, int index)
|
|
{
|
|
return ::lua_iscfunction(toState, index) != 0;
|
|
}
|
|
|
|
static void lua_pushnil(IntPtr luaState)
|
|
{
|
|
::lua_pushnil(toState);
|
|
}
|
|
|
|
|
|
|
|
static void lua_call(IntPtr luaState, int nArgs, int nResults)
|
|
{
|
|
::lua_call(toState, nArgs, nResults);
|
|
}
|
|
|
|
static int lua_pcall(IntPtr luaState, int nArgs, int nResults, int errfunc)
|
|
{
|
|
return ::lua_pcall(toState, nArgs, nResults, errfunc);
|
|
}
|
|
|
|
// static int lua_rawcall(IntPtr luaState, int nArgs, int nResults)
|
|
|
|
static IntPtr lua_tocfunction(IntPtr luaState, int index)
|
|
{
|
|
return IntPtr(::lua_tocfunction(toState, index));
|
|
}
|
|
|
|
static double lua_tonumber(IntPtr luaState, int index)
|
|
{
|
|
return ::lua_tonumber(toState, index);
|
|
}
|
|
|
|
|
|
static bool lua_toboolean(IntPtr luaState, int index)
|
|
{
|
|
return ::lua_toboolean(toState, index);
|
|
}
|
|
|
|
// unwrapped
|
|
// was out strLen
|
|
// static IntPtr lua_tolstring(IntPtr luaState, int index, [Out] int ^ strLen);
|
|
|
|
#undef lua_tostring
|
|
|
|
static String^ lua_tostring(IntPtr luaState, int index)
|
|
{
|
|
#if 1
|
|
// FIXME use the same format string as lua i.e. LUA_NUMBER_FMT
|
|
LuaTypes t = lua_type(luaState,index);
|
|
|
|
if(t == LuaTypes::LUA_TNUMBER)
|
|
return String::Format("{0}", lua_tonumber(luaState, index));
|
|
else if(t == LuaTypes::LUA_TSTRING)
|
|
{
|
|
size_t strlen;
|
|
|
|
const char *str = ::lua_tolstring(toState, index, &strlen);
|
|
return Marshal::PtrToStringAnsi(IntPtr((char *) str), strlen);
|
|
}
|
|
else if(t == LuaTypes::LUA_TNIL)
|
|
return nullptr; // treat lua nulls to as C# nulls
|
|
else
|
|
return gcnew String("0"); // Because luaV_tostring does this
|
|
#else
|
|
|
|
|
|
size_t strlen;
|
|
|
|
// Note! This method will _change_ the representation of the object on the stack to a string.
|
|
// We do not want this behavior so we do the conversion ourselves
|
|
const char *str = ::lua_tolstring(toState, index, &strlen);
|
|
if (str)
|
|
return Marshal::PtrToStringAnsi(IntPtr((char *) str), strlen);
|
|
else
|
|
return nullptr; // treat lua nulls to as C# nulls
|
|
#endif
|
|
}
|
|
|
|
static void lua_atpanic(IntPtr luaState, LuaCSFunction^ panicf)
|
|
{
|
|
IntPtr p = Marshal::GetFunctionPointerForDelegate(panicf);
|
|
::lua_atpanic(toState, (lua_CFunction) p.ToPointer());
|
|
}
|
|
|
|
#if 0
|
|
// no longer needed - all our functions are now stdcall calling convention
|
|
static int stdcall_closure(lua_State *L) {
|
|
lua_CFunction fn = (lua_CFunction)lua_touserdata(L, lua_upvalueindex(1));
|
|
return fn(L);
|
|
}
|
|
#endif
|
|
|
|
static void lua_pushstdcallcfunction(IntPtr luaState, LuaCSFunction^ function)
|
|
{
|
|
IntPtr p = Marshal::GetFunctionPointerForDelegate(function);
|
|
lua_pushcfunction(toState, (lua_CFunction) p.ToPointer());
|
|
}
|
|
|
|
|
|
#if 0
|
|
// not yet implemented
|
|
static void lua_atlock(IntPtr luaState, LuaCSFunction^ lockf)
|
|
{
|
|
IntPtr p = Marshal::GetFunctionPointerForDelegate(lockf);
|
|
::lua_atlock(toState, (lua_CFunction) p.ToPointer());
|
|
}
|
|
|
|
static void lua_atunlock(IntPtr luaState, LuaCSFunction^ unlockf);
|
|
#endif
|
|
|
|
static void lua_pushnumber(IntPtr luaState, double number)
|
|
{
|
|
::lua_pushnumber(toState, number);
|
|
}
|
|
|
|
static void lua_pushboolean(IntPtr luaState, bool value)
|
|
{
|
|
::lua_pushboolean(toState, value);
|
|
}
|
|
|
|
#if 0
|
|
// Not yet wrapped
|
|
static void lua_pushlstring(IntPtr luaState, String^ str, int size)
|
|
{
|
|
char *cs = (char *) Marshal::StringToHGlobalAnsi(str).ToPointer();
|
|
|
|
//
|
|
|
|
Marshal::FreeHGlobal(IntPtr(cs));
|
|
}
|
|
#endif
|
|
|
|
|
|
static void lua_pushstring(IntPtr luaState, String^ str)
|
|
{
|
|
char *cs = (char *) Marshal::StringToHGlobalAnsi(str).ToPointer();
|
|
|
|
::lua_pushstring(toState, cs);
|
|
|
|
Marshal::FreeHGlobal(IntPtr(cs));
|
|
}
|
|
|
|
|
|
static int luaL_newmetatable(IntPtr luaState, String^ meta)
|
|
{
|
|
char *cs = (char *) Marshal::StringToHGlobalAnsi(meta).ToPointer();
|
|
|
|
int result = ::luaL_newmetatable(toState, cs);
|
|
|
|
Marshal::FreeHGlobal(IntPtr(cs));
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
// steffenj: BEGIN Lua 5.1.1 API change (luaL_getmetatable is now a macro using lua_getfield)
|
|
static void lua_getfield(IntPtr luaState, int stackPos, String^ meta)
|
|
{
|
|
char *cs = (char *) Marshal::StringToHGlobalAnsi(meta).ToPointer();
|
|
|
|
::lua_getfield(toState, stackPos, cs);
|
|
|
|
Marshal::FreeHGlobal(IntPtr(cs));
|
|
}
|
|
|
|
#undef luaL_getmetatable
|
|
|
|
static void luaL_getmetatable(IntPtr luaState, String^ meta)
|
|
{
|
|
lua_getfield(luaState, (int) LuaIndexes::LUA_REGISTRYINDEX, meta);
|
|
}
|
|
|
|
static IntPtr luaL_checkudata(IntPtr luaState, int stackPos, String^ meta)
|
|
{
|
|
char *cs = (char *) Marshal::StringToHGlobalAnsi(meta).ToPointer();
|
|
|
|
void *result = ::luaL_checkudata(toState, stackPos, cs);
|
|
|
|
Marshal::FreeHGlobal(IntPtr(cs));
|
|
|
|
return IntPtr(result);
|
|
}
|
|
|
|
static bool luaL_getmetafield(IntPtr luaState, int stackPos, String^ field)
|
|
{
|
|
char *cs = (char *) Marshal::StringToHGlobalAnsi(field).ToPointer();
|
|
|
|
int result = ::luaL_getmetafield(toState, stackPos, cs);
|
|
|
|
Marshal::FreeHGlobal(IntPtr(cs));
|
|
|
|
return result != 0;
|
|
}
|
|
|
|
// wrapper not yet implemented
|
|
// static int lua_load(IntPtr luaState, LuaChunkReader chunkReader, ref ReaderInfo data, String^ chunkName);
|
|
|
|
static int luaL_loadbuffer(IntPtr luaState, String^ buff, String^ name)
|
|
{
|
|
char *cs1 = (char *) Marshal::StringToHGlobalAnsi(buff).ToPointer();
|
|
char *cs2 = (char *) Marshal::StringToHGlobalAnsi(name).ToPointer();
|
|
|
|
//CP: fix for MBCS, changed to use cs1's length (reported by qingrui.li)
|
|
int result = ::luaL_loadbuffer(toState, cs1, strlen(cs1), cs2);
|
|
|
|
Marshal::FreeHGlobal(IntPtr(cs1));
|
|
Marshal::FreeHGlobal(IntPtr(cs2));
|
|
|
|
return result;
|
|
}
|
|
|
|
static int luaL_loadfile(IntPtr luaState, String^ filename)
|
|
{
|
|
char *cs = (char *) Marshal::StringToHGlobalAnsi(filename).ToPointer();
|
|
int result = ::luaL_loadfile(toState, cs);
|
|
|
|
Marshal::FreeHGlobal(IntPtr(cs));
|
|
|
|
return result;
|
|
}
|
|
|
|
static void lua_error(IntPtr luaState)
|
|
{
|
|
::lua_error(toState);
|
|
}
|
|
|
|
|
|
static bool lua_checkstack(IntPtr luaState,int extra)
|
|
{
|
|
return ::lua_checkstack(toState, extra) != 0;
|
|
}
|
|
|
|
|
|
static int lua_next(IntPtr luaState,int index)
|
|
{
|
|
return ::lua_next(toState, index);
|
|
}
|
|
|
|
|
|
|
|
|
|
static void lua_pushlightuserdata(IntPtr luaState, IntPtr udata)
|
|
{
|
|
::lua_pushlightuserdata(toState, udata.ToPointer());
|
|
}
|
|
|
|
static int luanet_rawnetobj(IntPtr luaState,int obj)
|
|
{
|
|
int *udata= (int *) lua_touserdata(luaState, obj).ToPointer();
|
|
if(udata!=NULL) return *udata;
|
|
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:
|
|
|
|
// Starting with 5.1 the auxlib version of checkudata throws an exception if the type isn't right
|
|
// Instead, we want to run our own version that checks the type and just returns null for failure
|
|
static void *checkudata_raw(lua_State *L, int ud, const char *tname)
|
|
{
|
|
void *p = ::lua_touserdata(L, ud);
|
|
|
|
if (p != NULL)
|
|
{ /* value is a userdata? */
|
|
if (::lua_getmetatable(L, ud))
|
|
{
|
|
int isEqual;
|
|
|
|
/* does it have a metatable? */
|
|
::lua_getfield(L, (int) LuaIndexes::LUA_REGISTRYINDEX, tname); /* get correct metatable */
|
|
|
|
isEqual = lua_rawequal(L, -1, -2);
|
|
|
|
// NASTY - we need our own version of the lua_pop macro
|
|
// lua_pop(L, 2); /* remove both metatables */
|
|
::lua_settop(L, -(2) - 1);
|
|
|
|
if (isEqual) /* does it have the correct mt? */
|
|
return p;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
public:
|
|
|
|
static int luanet_checkudata(IntPtr luaState, int ud, String ^tname)
|
|
{
|
|
char *cs = (char *) Marshal::StringToHGlobalAnsi(tname).ToPointer();
|
|
|
|
int *udata=(int*) checkudata_raw(toState, ud, cs);
|
|
|
|
Marshal::FreeHGlobal(IntPtr(cs));
|
|
|
|
if(udata!=NULL) return *udata;
|
|
return -1;
|
|
}
|
|
|
|
|
|
static bool luaL_checkmetatable(IntPtr luaState,int index)
|
|
{
|
|
int retVal=0;
|
|
|
|
if(lua_getmetatable(luaState,index)!=0)
|
|
{
|
|
lua_pushlightuserdata(luaState, IntPtr(&tag));
|
|
lua_rawget(luaState, -2);
|
|
retVal = !lua_isnil(luaState, -1);
|
|
lua_settop(luaState, -3);
|
|
}
|
|
return retVal;
|
|
}
|
|
|
|
static IntPtr luanet_gettag()
|
|
{
|
|
return IntPtr(&tag);
|
|
}
|
|
|
|
static void luanet_newudata(IntPtr luaState,int val)
|
|
{
|
|
int* pointer=(int*) lua_newuserdata(luaState, sizeof(int)).ToPointer();
|
|
*pointer=val;
|
|
}
|
|
|
|
static int luanet_tonetobject(IntPtr luaState,int index)
|
|
{
|
|
int *udata;
|
|
|
|
if(lua_type(luaState,index)==LuaTypes::LUA_TUSERDATA)
|
|
{
|
|
if(luaL_checkmetatable(luaState, index))
|
|
{
|
|
udata=(int*) lua_touserdata(luaState,index).ToPointer();
|
|
if(udata!=NULL)
|
|
return *udata;
|
|
}
|
|
|
|
udata=(int*)checkudata_raw(toState,index, "luaNet_class");
|
|
if(udata!=NULL) return *udata;
|
|
udata=(int*)checkudata_raw(toState,index, "luaNet_searchbase");
|
|
if(udata!=NULL) return *udata;
|
|
udata=(int*)checkudata_raw(toState,index, "luaNet_function");
|
|
if(udata!=NULL) return *udata;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
|
|
#if 0
|
|
|
|
|
|
[DllImport(STUBDLL,CallingConvention=CallingConvention.Cdecl)]
|
|
|
|
#endif
|
|
};
|
|
}
|