Commit 00eddcac authored by Megax's avatar Megax
Browse files

* Kisebb modositasok.

parent a0afbf36
...@@ -277,8 +277,6 @@ namespace KopiLua ...@@ -277,8 +277,6 @@ namespace KopiLua
public static int lua_rawequal (lua_State L, int index1, int index2) { public static int lua_rawequal (lua_State L, int index1, int index2) {
StkId o1 = index2adr(L, index1); StkId o1 = index2adr(L, index1);
StkId o2 = index2adr(L, index2); StkId o2 = index2adr(L, index2);
Console.WriteLine("lua_rawequal: {0}", (o1 == luaO_nilobject || o2 == luaO_nilobject));
Console.WriteLine("lua_rawequal2: {0}", luaO_rawequalObj(o1, o2));
return (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 return (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0
: luaO_rawequalObj(o1, o2); : luaO_rawequalObj(o1, o2);
} }
...@@ -392,11 +390,10 @@ namespace KopiLua ...@@ -392,11 +390,10 @@ namespace KopiLua
public static uint lua_touserdata2 (lua_State L, int idx) { public static uint lua_touserdata2 (lua_State L, int idx) {
StkId o = index2adr(L, idx); StkId o = index2adr(L, idx);
Console.WriteLine("x0:{0}", o);
switch (ttype(o)) { switch (ttype(o)) {
case LUA_TUSERDATA: Console.WriteLine("x:{0}", rawuvalue(o).len); return (rawuvalue(o).len); case LUA_TUSERDATA: return (rawuvalue(o).len);
case LUA_TLIGHTUSERDATA: Console.WriteLine("x2:{0}", rawuvalue(o).len); return (rawuvalue(o).len); case LUA_TLIGHTUSERDATA: return (rawuvalue(o).len);
default: Console.WriteLine("x3:{0}", 0); return 0; default: return 0;
} }
} }
...@@ -556,7 +553,6 @@ namespace KopiLua ...@@ -556,7 +553,6 @@ namespace KopiLua
} }
public static void lua_getfield (lua_State L, int idx, CharPtr k) { public static void lua_getfield (lua_State L, int idx, CharPtr k) {
Console.WriteLine("lllll:{0}", k);
StkId t; StkId t;
TValue key = new TValue(); TValue key = new TValue();
lua_lock(L); lua_lock(L);
...@@ -624,7 +620,6 @@ namespace KopiLua ...@@ -624,7 +620,6 @@ namespace KopiLua
res = 1; res = 1;
} }
lua_unlock(L); lua_unlock(L);
Console.WriteLine("nulllll: {0}", res);
return res; return res;
} }
...@@ -835,7 +830,6 @@ namespace KopiLua ...@@ -835,7 +830,6 @@ namespace KopiLua
api_checkvalidindex(L, o); api_checkvalidindex(L, o);
func = savestack(L, o); func = savestack(L, o);
} }
Console.WriteLine("func:{0}", func);
c.func = L.top - (nargs+1); /* function to be called */ c.func = L.top - (nargs+1); /* function to be called */
c.nresults = nresults; c.nresults = nresults;
status = luaD_pcall(L, f_call, c, savestack(L, c.func), func); status = luaD_pcall(L, f_call, c, savestack(L, c.func), func);
......
...@@ -758,7 +758,6 @@ namespace KopiLua ...@@ -758,7 +758,6 @@ namespace KopiLua
public static int luaO_rawequalObj (TValue t1, TValue t2) { public static int luaO_rawequalObj (TValue t1, TValue t2) {
Console.WriteLine("luaO_rawequalObj: {0}", ttype(t1) != ttype(t2));
if (ttype(t1) != ttype(t2)) return 0; if (ttype(t1) != ttype(t2)) return 0;
else switch (ttype(t1)) { else switch (ttype(t1)) {
case LUA_TNIL: case LUA_TNIL:
...@@ -771,9 +770,6 @@ namespace KopiLua ...@@ -771,9 +770,6 @@ namespace KopiLua
return pvalue(t1) == pvalue(t2) ? 1 : 0; return pvalue(t1) == pvalue(t2) ? 1 : 0;
default: default:
lua_assert(iscollectable(t1)); lua_assert(iscollectable(t1));
Console.WriteLine("luaO_rawequalObj1-0: {0}", gcvalue(t1));
Console.WriteLine("luaO_rawequalObj1-1: {0}", gcvalue(t2));
Console.WriteLine("luaO_rawequalObj1: {0}", gcvalue(t1) == gcvalue(t2));
return gcvalue(t1) == gcvalue(t2) ? 1 : 0; return gcvalue(t1) == gcvalue(t2) ? 1 : 0;
} }
} }
......
...@@ -107,7 +107,6 @@ namespace KopiLua ...@@ -107,7 +107,6 @@ namespace KopiLua
} }
//return newlstr(L, str, l, h); /* not found */ //return newlstr(L, str, l, h); /* not found */
TString res = newlstr(L, str, l, h); TString res = newlstr(L, str, l, h);
Console.WriteLine(res);
return res; return res;
} }
......
...@@ -237,11 +237,8 @@ namespace LuaInterface ...@@ -237,11 +237,8 @@ namespace LuaInterface
public object[] DoFile(string fileName) public object[] DoFile(string fileName)
{ {
int oldTop=KopiLua.Lua.lua_gettop(luaState); int oldTop=KopiLua.Lua.lua_gettop(luaState);
//Console.WriteLine("aaa: {0}",oldTop);
if(KopiLua.Lua.luaL_loadfile(luaState,fileName)==0) if(KopiLua.Lua.luaL_loadfile(luaState,fileName)==0)
{ {
//Console.WriteLine("aaa2: {0}",KopiLua.Lua.lua_pcall(luaState, 0, -1, 0));
//Console.WriteLine("zzzzzzzzzzzzzzzzzz");
if (KopiLua.Lua.lua_pcall(luaState, 0, -1, 0) == 0) if (KopiLua.Lua.lua_pcall(luaState, 0, -1, 0) == 0)
return translator.popValues(luaState, oldTop); return translator.popValues(luaState, oldTop);
else else
...@@ -348,7 +345,8 @@ namespace LuaInterface ...@@ -348,7 +345,8 @@ namespace LuaInterface
public LuaFunction GetFunction(string fullPath) public LuaFunction GetFunction(string fullPath)
{ {
object obj=this[fullPath]; object obj=this[fullPath];
return (obj is KopiLua.Lua.lua_CFunction ? new LuaFunction((KopiLua.Lua.lua_CFunction)obj,this) : (LuaFunction)obj); //return (obj is KopiLua.Lua.lua_CFunction ? new LuaFunction((KopiLua.Lua.lua_CFunction)obj,this) : (LuaFunction)obj);
return (obj is KopiLua.Lua.lua_CFunction ? new LuaFunction((KopiLua.Lua.lua_CFunction)obj,this) : /*(LuaFunction)*/new LuaFunction(obj.GetHashCode(), this));
} }
/* /*
* Gets a function global variable as a delegate of * Gets a function global variable as a delegate of
...@@ -533,7 +531,7 @@ namespace LuaInterface ...@@ -533,7 +531,7 @@ namespace LuaInterface
* Registers an object's method as a Lua function (global or table field) * Registers an object's method as a Lua function (global or table field)
* The method may have any signature * The method may have any signature
*/ */
public LuaFunction RegisterFunction(string path, object target,MethodInfo function) public LuaFunction RegisterFunction(string path, object target,MethodInfo function)
{ {
// We leave nothing on the stack when we are done // We leave nothing on the stack when we are done
int oldTop = KopiLua.Lua.lua_gettop(luaState); int oldTop = KopiLua.Lua.lua_gettop(luaState);
...@@ -545,7 +543,6 @@ namespace LuaInterface ...@@ -545,7 +543,6 @@ namespace LuaInterface
LuaFunction f = GetFunction(path); LuaFunction f = GetFunction(path);
KopiLua.Lua.lua_settop(luaState, oldTop); KopiLua.Lua.lua_settop(luaState, oldTop);
return f; return f;
} }
......
...@@ -270,7 +270,7 @@ namespace LuaWrap ...@@ -270,7 +270,7 @@ namespace LuaWrap
public static int luanet_rawnetobj(Lua.lua_State luaState,int obj) public static int luanet_rawnetobj(Lua.lua_State luaState,int obj)
{ {
int udata= Convert.ToInt32(Lua.lua_touserdata2(luaState, obj)); int udata= (int)Lua.lua_touserdata2(luaState, obj);
if(udata!=0) if(udata!=0)
return udata; return udata;
return -1; return -1;
...@@ -284,25 +284,19 @@ namespace LuaWrap ...@@ -284,25 +284,19 @@ namespace LuaWrap
public static int checkudata_raw(Lua.lua_State luaState, int ud, string tname) public static int checkudata_raw(Lua.lua_State luaState, int ud, string tname)
{ {
int p = (int)Lua.lua_touserdata2(luaState, ud); int p = (int)Lua.lua_touserdata2(luaState, ud);
Console.WriteLine("z:{0}", p);
if(p != 0) if(p != 0)
{ {
/* value is a userdata? */ /* value is a userdata? */
Console.WriteLine("z0:{0}", p);
//Console.WriteLine("z2:{0}", Lua.lua_getmetatable(luaState, ud));
if(Lua.lua_getmetatable(luaState, ud)!=0) if(Lua.lua_getmetatable(luaState, ud)!=0)
{ {
/* does it have a metatable? */ /* does it have a metatable? */
Console.WriteLine("z1:{0}", p);
Lua.lua_getfield(luaState, (int)PseudoIndex.Registry, tname); /* get correct metatable */ Lua.lua_getfield(luaState, (int)PseudoIndex.Registry, tname); /* get correct metatable */
//Console.WriteLine("z3:{0}", p);
bool isEqual = Lua.lua_rawequal(luaState, -1, -2).ToBoolean(); bool isEqual = Lua.lua_rawequal(luaState, -1, -2).ToBoolean();
Console.WriteLine("z2:{0}", p);
Console.WriteLine("z2-1:{0}", isEqual);
// NASTY - we need our own version of the lua_pop macro // NASTY - we need our own version of the lua_pop macro
// lua_pop(L, 2); /* remove both metatables */ // lua_pop(L, 2); /* remove both metatables */
Lua.lua_settop(luaState, -(2) - 1); Lua.lua_settop(luaState, -(2) - 1);
Console.WriteLine("z3:{0}", p);
if(isEqual) /* does it have the correct mt? */ if(isEqual) /* does it have the correct mt? */
return p; return p;
} }
...@@ -330,29 +324,23 @@ Console.WriteLine("z3:{0}", p); ...@@ -330,29 +324,23 @@ Console.WriteLine("z3:{0}", p);
{ {
int udata; int udata;
Console.WriteLine("asd:"+(Lua.lua_type(luaState, index).ToLuaType() == LuaType.UserData).ToString());
Console.WriteLine("asd:1"+Lua.lua_type(luaState, index));
if(Lua.lua_type(luaState, index).ToLuaType() == LuaType.UserData) if(Lua.lua_type(luaState, index).ToLuaType() == LuaType.UserData)
{ {
if(luaL_checkmetatable(luaState, index)) if(luaL_checkmetatable(luaState, index))
{ {
udata = (int)Lua.lua_touserdata2(luaState, index); udata = (int)Lua.lua_touserdata2(luaState, index);
Console.WriteLine("asd0:{0}",udata);
if(udata != 0) if(udata != 0)
return udata; return udata;
} }
udata = checkudata_raw(luaState, index, "luaNet_class"); udata = checkudata_raw(luaState, index, "luaNet_class");
Console.WriteLine("asd2:{0}",udata);
if(udata != 0) if(udata != 0)
return udata; return udata;
udata = checkudata_raw(luaState, index, "luaNet_searchbase"); udata = checkudata_raw(luaState, index, "luaNet_searchbase");
Console.WriteLine("asd3:{0}",udata);
if(udata != 0) if(udata != 0)
return udata; return udata;
udata = checkudata_raw(luaState, index, "luaNet_function"); udata = checkudata_raw(luaState, index, "luaNet_function");
Console.WriteLine("asd4:{0}",udata);
if(udata != 0) if(udata != 0)
return udata; return udata;
} }
......
namespace LuaInterface namespace LuaInterface
{ {
using System; using System;
using System.IO; using System.IO;
using System.Collections; using System.Collections;
using System.Reflection; using System.Reflection;
using System.Diagnostics; using System.Diagnostics;
using System.Collections.Generic; using System.Collections.Generic;
using LuaWrap; using LuaWrap;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
/* /*
* Functions used in the metatables of userdata representing * Functions used in the metatables of userdata representing
* CLR objects * CLR objects
* *
* Author: Fabio Mascarenhas * Author: Fabio Mascarenhas
* Version: 1.0 * Version: 1.0
*/ */
class MetaFunctions class MetaFunctions
{ {
/* /*
* __index metafunction for CLR objects. Implemented in Lua. * __index metafunction for CLR objects. Implemented in Lua.
*/ */
internal static string luaIndexFunction = internal static string luaIndexFunction =
"local function index(obj,name)\n" + "local function index(obj,name)\n" +
" local meta=getmetatable(obj)\n" + " local meta=getmetatable(obj)\n" +
" local cached=meta.cache[name]\n" + " local cached=meta.cache[name]\n" +
" if cached~=nil then\n" + " if cached~=nil then\n" +
" return cached\n" + " return cached\n" +
" else\n" + " else\n" +
" local value,isFunc=get_object_member(obj,name)\n" + " local value,isFunc=get_object_member(obj,name)\n" +
" if isFunc then\n" + " if isFunc then\n" +
" meta.cache[name]=value\n" + " meta.cache[name]=value\n" +
" end\n" + " end\n" +
" return value\n" + " return value\n" +
" end\n" + " end\n" +
"end\n" + "end\n" +
"return index"; "return index";
private ObjectTranslator translator; private ObjectTranslator translator;
private Hashtable memberCache = new Hashtable(); private Hashtable memberCache = new Hashtable();
internal KopiLua.Lua.lua_CFunction gcFunction, indexFunction, newindexFunction, internal KopiLua.Lua.lua_CFunction gcFunction, indexFunction, newindexFunction,
baseIndexFunction, classIndexFunction, classNewindexFunction, baseIndexFunction, classIndexFunction, classNewindexFunction,
execDelegateFunction, callConstructorFunction, toStringFunction; execDelegateFunction, callConstructorFunction, toStringFunction;
public MetaFunctions(ObjectTranslator translator) public MetaFunctions(ObjectTranslator translator)
{ {
this.translator = translator; this.translator = translator;
gcFunction = new KopiLua.Lua.lua_CFunction(this.collectObject); gcFunction = new KopiLua.Lua.lua_CFunction(this.collectObject);
toStringFunction = new KopiLua.Lua.lua_CFunction(this.toString); toStringFunction = new KopiLua.Lua.lua_CFunction(this.toString);
indexFunction = new KopiLua.Lua.lua_CFunction(this.getMethod); indexFunction = new KopiLua.Lua.lua_CFunction(this.getMethod);
newindexFunction = new KopiLua.Lua.lua_CFunction(this.setFieldOrProperty); newindexFunction = new KopiLua.Lua.lua_CFunction(this.setFieldOrProperty);
baseIndexFunction = new KopiLua.Lua.lua_CFunction(this.getBaseMethod); baseIndexFunction = new KopiLua.Lua.lua_CFunction(this.getBaseMethod);
callConstructorFunction = new KopiLua.Lua.lua_CFunction(this.callConstructor); callConstructorFunction = new KopiLua.Lua.lua_CFunction(this.callConstructor);
classIndexFunction = new KopiLua.Lua.lua_CFunction(this.getClassMethod); classIndexFunction = new KopiLua.Lua.lua_CFunction(this.getClassMethod);
classNewindexFunction = new KopiLua.Lua.lua_CFunction(this.setClassFieldOrProperty); classNewindexFunction = new KopiLua.Lua.lua_CFunction(this.setClassFieldOrProperty);
execDelegateFunction = new KopiLua.Lua.lua_CFunction(this.runFunctionDelegate); execDelegateFunction = new KopiLua.Lua.lua_CFunction(this.runFunctionDelegate);
} }
/* /*
* __call metafunction of CLR delegates, retrieves and calls the delegate. * __call metafunction of CLR delegates, retrieves and calls the delegate.
*/ */
private int runFunctionDelegate(KopiLua.Lua.lua_State luaState) private int runFunctionDelegate(KopiLua.Lua.lua_State luaState)
{ {
KopiLua.Lua.lua_CFunction func = (KopiLua.Lua.lua_CFunction)translator.getRawNetObject(luaState, 1); KopiLua.Lua.lua_CFunction func = (KopiLua.Lua.lua_CFunction)translator.getRawNetObject(luaState, 1);
KopiLua.Lua.lua_remove(luaState, 1); KopiLua.Lua.lua_remove(luaState, 1);
return func(luaState); return func(luaState);
} }
/* /*
* __gc metafunction of CLR objects. * __gc metafunction of CLR objects.
*/ */
private int collectObject(KopiLua.Lua.lua_State luaState) private int collectObject(KopiLua.Lua.lua_State luaState)
{ {
int udata = LuaLib.luanet_rawnetobj(luaState, 1); int udata = LuaLib.luanet_rawnetobj(luaState, 1);
if (udata != -1) if (udata != -1)
{ {
translator.collectObject(udata); translator.collectObject(udata);
} }
else else
{ {
// Debug.WriteLine("not found: " + udata); // Debug.WriteLine("not found: " + udata);
} }
return 0; return 0;
} }
/* /*
* __tostring metafunction of CLR objects. * __tostring metafunction of CLR objects.
*/ */
private int toString(KopiLua.Lua.lua_State luaState) private int toString(KopiLua.Lua.lua_State luaState)
{ {
object obj = translator.getRawNetObject(luaState, 1); object obj = translator.getRawNetObject(luaState, 1);
if (obj != null) if (obj != null)
{ {
translator.push(luaState, obj.ToString() + ": " + obj.GetHashCode()); translator.push(luaState, obj.ToString() + ": " + obj.GetHashCode());
} }
else KopiLua.Lua.lua_pushnil(luaState); else KopiLua.Lua.lua_pushnil(luaState);
return 1; return 1;
} }
/// <summary>
/// <summary> /// Debug tool to dump the lua stack
/// Debug tool to dump the lua stack /// </summary>
/// </summary> /// FIXME, move somewhere else
/// FIXME, move somewhere else public static void dumpStack(ObjectTranslator translator, KopiLua.Lua.lua_State luaState)
public static void dumpStack(ObjectTranslator translator, KopiLua.Lua.lua_State luaState) {
{ int depth = KopiLua.Lua.lua_gettop(luaState);
int depth = KopiLua.Lua.lua_gettop(luaState);
Debug.WriteLine("lua stack depth: " + depth);
Debug.WriteLine("lua stack depth: " + depth); for (int i = 1; i <= depth; i++)
for (int i = 1; i <= depth; i++) {
{ LuaType type = KopiLua.Lua.lua_type(luaState, i).ToLuaType();
LuaType type = KopiLua.Lua.lua_type(luaState, i).ToLuaType(); // we dump stacks when deep in calls, calling typename while the stack is in flux can fail sometimes, so manually check for key types
// we dump stacks when deep in calls, calling typename while the stack is in flux can fail sometimes, so manually check for key types string typestr = (type == LuaType.Table) ? "table" : KopiLua.Lua.lua_typename(luaState, Convert.ToInt32(type)).ToString();
string typestr = (type == LuaType.Table) ? "table" : KopiLua.Lua.lua_typename(luaState, Convert.ToInt32(type)).ToString();
string strrep = KopiLua.Lua.lua_tostring(luaState, i).ToString();
string strrep = KopiLua.Lua.lua_tostring(luaState, i).ToString(); if (type == LuaType.UserData)
if (type == LuaType.UserData) {
{ object obj = translator.getRawNetObject(luaState, i);
object obj = translator.getRawNetObject(luaState, i); strrep = obj.ToString();
strrep = obj.ToString(); }
}
Debug.Print("{0}: ({1}) {2}", i, typestr, strrep);
Debug.Print("{0}: ({1}) {2}", i, typestr, strrep); }
} }
}
/*
* Called by the __index metafunction of CLR objects in case the
/* * method is not cached or it is a field/property/event.
* Called by the __index metafunction of CLR objects in case the * Receives the object and the member name as arguments and returns
* method is not cached or it is a field/property/event. * either the value of the member or a delegate to call it.
* Receives the object and the member name as arguments and returns * If the member does not exist returns nil.
* either the value of the member or a delegate to call it. */
* If the member does not exist returns nil. private int getMethod(KopiLua.Lua.lua_State luaState)
*/ {
private int getMethod(KopiLua.Lua.lua_State luaState) object obj = translator.getRawNetObject(luaState, 1);
{ if (obj == null)
object obj = translator.getRawNetObject(luaState, 1); {
if (obj == null) translator.throwError(luaState, "trying to index an invalid object reference");
{ KopiLua.Lua.lua_pushnil(luaState);
translator.throwError(luaState, "trying to index an invalid object reference"); return 1;
KopiLua.Lua.lua_pushnil(luaState); }
return 1;
} object index = translator.getObject(luaState, 2);
//Type indexType = index.GetType();
object index = translator.getObject(luaState, 2);
//Type indexType = index.GetType(); string methodName = index as string; // will be null if not a string arg
Type objType = obj.GetType();
string methodName = index as string; // will be null if not a string arg
Type objType = obj.GetType(); // Handle the most common case, looking up the method by name
if (methodName != null && isMemberPresent(objType, methodName))
// Handle the most common case, looking up the method by name return getMember(luaState, objType, obj, methodName, BindingFlags.Instance);
if (methodName != null && isMemberPresent(objType, methodName))
return getMember(luaState, objType, obj, methodName, BindingFlags.Instance); // Try to access by array if the type is right and index is an int (lua numbers always come across as double)
if (objType.IsArray && index is double)
// Try to access by array if the type is right and index is an int (lua numbers always come across as double) {
if (objType.IsArray && index is double) object[] arr = (object[])obj;
{
object[] arr = (object[])obj; translator.push(luaState, arr[(int)((double)index)]);
}
translator.push(luaState, arr[(int)((double)index)]); else
} {
else // Try to use get_Item to index into this .net object
{ MethodInfo getter = objType.GetMethod("get_Item");
// Try to use get_Item to index into this .net object ParameterInfo[] actualParms = (getter != null) ? getter.GetParameters() : null;
MethodInfo getter = objType.GetMethod("get_Item");
ParameterInfo[] actualParms = (getter != null) ? getter.GetParameters() : null; if (actualParms == null || actualParms.Length != 1)
{
if (actualParms == null || actualParms.Length != 1) translator.throwError(luaState, "method not found (or no indexer): " + index);
{
translator.throwError(luaState, "method not found (or no indexer): " + index); KopiLua.Lua.lua_pushnil(luaState);
}
KopiLua.Lua.lua_pushnil(luaState); else
} {
else // Get the index in a form acceptable to the getter
{ index = translator.getAsType(luaState, 2, actualParms[0].ParameterType);
// Get the index in a form acceptable to the getter
index = translator.getAsType(luaState, 2, actualParms[0].ParameterType); object[] args = new object[1];
object[] args = new object[1]; // Just call the indexer - if out of bounds an exception will happen
args[0] = index;
// Just call the indexer - if out of bounds an exception will happen try
args[0] = index; {
try object result = getter.Invoke(obj, args);
{ translator.push(luaState, result);
object result = getter.Invoke(obj, args); }
translator.push(luaState, result); catch (TargetInvocationException e)
} {
catch (TargetInvocationException e) // Provide a more readable description for the common case of key not found
{ if(e.InnerException is KeyNotFoundException)
// Provide a more readable description for the common case of key not found translator.throwError(luaState, "key '" + index + "' not found ");
if(e.InnerException is KeyNotFoundException) else
translator.throwError(luaState, "key '" + index + "' not found "); translator.throwError(luaState, "exception indexing '" + index + "' " + e.Message);
else
translator.throwError(luaState, "exception indexing '" + index + "' " + e.Message); KopiLua.Lua.lua_pushnil(luaState);
}
KopiLua.Lua.lua_pushnil(luaState); }
} }
}
} KopiLua.Lua.lua_pushboolean(luaState, 0);
return 2;
KopiLua.Lua.lua_pushboolean(luaState, 0); }
return 2;
}
/*
* __index metafunction of base classes (the base field of Lua tables).
/* * Adds a prefix to the method name to call the base version of the method.
* __index metafunction of base classes (the base field of Lua tables). */
* Adds a prefix to the method name to call the base version of the method. private int getBaseMethod(KopiLua.Lua.lua_State luaState)
*/ {
private int getBaseMethod(KopiLua.Lua.lua_State luaState) object obj = translator.getRawNetObject(luaState, 1);
{ if (obj == null)
object obj = translator.getRawNetObject(luaState, 1); {
if (obj == null) translator.throwError(luaState, "trying to index an invalid object reference");
{ KopiLua.Lua.lua_pushnil(luaState);
translator.throwError(luaState, "trying to index an invalid object reference"); KopiLua.Lua.lua_pushboolean(luaState, 0);
KopiLua.Lua.lua_pushnil(luaState); return 2;
KopiLua.Lua.lua_pushboolean(luaState, 0); }
return 2; string methodName = KopiLua.Lua.lua_tostring(luaState, 2).ToString();
} if (methodName == null)
string methodName = KopiLua.Lua.lua_tostring(luaState, 2).ToString(); {
if (methodName == null) KopiLua.Lua.lua_pushnil(luaState);
{ KopiLua.Lua.lua_pushboolean(luaState, 0);
KopiLua.Lua.lua_pushnil(luaState); return 2;
KopiLua.Lua.lua_pushboolean(luaState, 0); }
return 2; getMember(luaState, obj.GetType(), obj, "__luaInterface_base_" + methodName, BindingFlags.Instance);
} KopiLua.Lua.lua_settop(luaState, -2);
getMember(luaState, obj.GetType(), obj, "__luaInterface_base_" + methodName, BindingFlags.Instance); if (KopiLua.Lua.lua_type(luaState, -1).ToLuaType() == LuaType.Nil)
KopiLua.Lua.lua_settop(luaState, -2); {
if (KopiLua.Lua.lua_type(luaState, -1).ToLuaType() == LuaType.Nil) KopiLua.Lua.lua_settop(luaState, -2);
{ return getMember(luaState, obj.GetType(), obj, methodName, BindingFlags.Instance);
KopiLua.Lua.lua_settop(luaState, -2); }
return getMember(luaState, obj.GetType(), obj, methodName, BindingFlags.Instance); KopiLua.Lua.lua_pushboolean(luaState, 0);
} return 2;
KopiLua.Lua.lua_pushboolean(luaState, 0); }
return 2;
}
/// <summary>
/// Does this method exist as either an instance or static?
/// <summary> /// </summary>
/// Does this method exist as either an instance or static? /// <param name="objType"></param>
/// </summary> /// <param name="methodName"></param>
/// <param name="objType"></param> /// <returns></returns>
/// <param name="methodName"></param> bool isMemberPresent(IReflect objType, string methodName)
/// <returns></returns> {
bool isMemberPresent(IReflect objType, string methodName) object cachedMember = checkMemberCache(memberCache, objType, methodName);
{
object cachedMember = checkMemberCache(memberCache, objType, methodName); if (cachedMember != null)
return true;
if (cachedMember != null)
return true; MemberInfo[] members = objType.GetMember(methodName, BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
return (members.Length > 0);
MemberInfo[] members = objType.GetMember(methodName, BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); }
return (members.Length > 0);
} /*
* Pushes the value of a member or a delegate to call it, depending on the type of
/* * the member. Works with static or instance members.
* Pushes the value of a member or a delegate to call it, depending on the type of * Uses reflection to find members, and stores the reflected MemberInfo object in
* the member. Works with static or instance members. * a cache (indexed by the type of the object and the name of the member).
* Uses reflection to find members, and stores the reflected MemberInfo object in */
* a cache (indexed by the type of the object and the name of the member). private int getMember(KopiLua.Lua.lua_State luaState, IReflect objType, object obj, string methodName, BindingFlags bindingType)
*/ {
private int getMember(KopiLua.Lua.lua_State luaState, IReflect objType, object obj, string methodName, BindingFlags bindingType) bool implicitStatic = false;
{ MemberInfo member = null;
bool implicitStatic = false; object cachedMember = checkMemberCache(memberCache, objType, methodName);
MemberInfo member = null; //object cachedMember=null;
object cachedMember = checkMemberCache(memberCache, objType, methodName); if (cachedMember is KopiLua.Lua.lua_CFunction)
//object cachedMember=null; {
if (cachedMember is KopiLua.Lua.lua_CFunction) translator.pushFunction(luaState, (KopiLua.Lua.lua_CFunction)cachedMember);
{ translator.push(luaState, true);
translator.pushFunction(luaState, (KopiLua.Lua.lua_CFunction)cachedMember); return 2;
translator.push(luaState, true); }
return 2; else if (cachedMember != null)
} {
else if (cachedMember != null) member = (MemberInfo)cachedMember;
{ }
member = (MemberInfo)cachedMember; else
} {
else MemberInfo[] members = objType.GetMember(methodName, bindingType | BindingFlags.Public | BindingFlags.NonPublic);
{ if (members.Length > 0)
MemberInfo[] members = objType.GetMember(methodName, bindingType | BindingFlags.Public | BindingFlags.NonPublic); member = members[0];
if (members.Length > 0) else
member = members[0]; {
else // If we can't find any suitable instance members, try to find them as statics - but we only want to allow implicit static
{ // lookups for fields/properties/events -kevinh
// If we can't find any suitable instance members, try to find them as statics - but we only want to allow implicit static members = objType.GetMember(methodName, bindingType | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
// lookups for fields/properties/events -kevinh
members = objType.GetMember(methodName, bindingType | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (members.Length > 0)
{
if (members.Length > 0) member = members[0];
{ implicitStatic = true;
member = members[0]; }
implicitStatic = true; }
} }
} if (member != null)
} {
if (member != null) if (member.MemberType == MemberTypes.Field)
{ {
if (member.MemberType == MemberTypes.Field) FieldInfo field = (FieldInfo)member;
{ if (cachedMember == null) setMemberCache(memberCache, objType, methodName, member);
FieldInfo field = (FieldInfo)member; try
if (cachedMember == null) setMemberCache(memberCache, objType, methodName, member); {
try translator.push(luaState, field.GetValue(obj));
{ }
translator.push(luaState, field.GetValue(obj)); catch
} {
catch KopiLua.Lua.lua_pushnil(luaState);
{ }
KopiLua.Lua.lua_pushnil(luaState); }
} else if (member.MemberType == MemberTypes.Property)
} {
else if (member.MemberType == MemberTypes.Property) PropertyInfo property = (PropertyInfo)member;
{ if (cachedMember == null) setMemberCache(memberCache, objType, methodName, member);
PropertyInfo property = (PropertyInfo)member; try
if (cachedMember == null) setMemberCache(memberCache, objType, methodName, member); {
try object val = property.GetValue(obj, null);
{
object val = property.GetValue(obj, null); translator.push(luaState, val);
}
translator.push(luaState, val); catch (ArgumentException)
} {
catch (ArgumentException) // If we can't find the getter in our class, recurse up to the base class and see
{ // if they can help.
// If we can't find the getter in our class, recurse up to the base class and see
// if they can help. if (objType is Type && !(((Type)objType) == typeof(object)))
return getMember(luaState, ((Type)objType).BaseType, obj, methodName, bindingType);
if (objType is Type && !(((Type)objType) == typeof(object))) else
return getMember(luaState, ((Type)objType).BaseType, obj, methodName, bindingType); KopiLua.Lua.lua_pushnil(luaState);
else }
KopiLua.Lua.lua_pushnil(luaState); catch(TargetInvocationException e) // Convert this exception into a Lua error
} {
catch(TargetInvocationException e) // Convert this exception into a Lua error ThrowError(luaState, e);
{ KopiLua.Lua.lua_pushnil(luaState);
ThrowError(luaState, e); }
KopiLua.Lua.lua_pushnil(luaState); }
} else if (member.MemberType == MemberTypes.Event)
} {
else if (member.MemberType == MemberTypes.Event) EventInfo eventInfo = (EventInfo)member;
{ if (cachedMember == null) setMemberCache(memberCache, objType, methodName, member);
EventInfo eventInfo = (EventInfo)member; translator.push(luaState, new RegisterEventHandler(translator.pendingEvents, obj, eventInfo));
if (cachedMember == null) setMemberCache(memberCache, objType, methodName, member); }
translator.push(luaState, new RegisterEventHandler(translator.pendingEvents, obj, eventInfo)); else if(!implicitStatic)
} {
else if(!implicitStatic) if (member.MemberType == MemberTypes.NestedType)
{ {
if (member.MemberType == MemberTypes.NestedType) // kevinh - added support for finding nested types
{
// kevinh - added support for finding nested types // cache us
if (cachedMember == null) setMemberCache(memberCache, objType, methodName, member);
// cache us
if (cachedMember == null) setMemberCache(memberCache, objType, methodName, member); // Find the name of our class
string name = member.Name;
// Find the name of our class Type dectype = member.DeclaringType;
string name = member.Name;
Type dectype = member.DeclaringType; // Build a new long name and try to find the type by name
string longname = dectype.FullName + "+" + name;
// Build a new long name and try to find the type by name Type nestedType = translator.FindType(longname);
string longname = dectype.FullName + "+" + name;
Type nestedType = translator.FindType(longname); translator.pushType(luaState, nestedType);
}
translator.pushType(luaState, nestedType); else
} {
else // Member type must be 'method'
{ KopiLua.Lua.lua_CFunction wrapper = new KopiLua.Lua.lua_CFunction((new LuaMethodWrapper(translator, objType, methodName, bindingType)).call);
// Member type must be 'method' if (cachedMember == null) setMemberCache(memberCache, objType, methodName, wrapper);
KopiLua.Lua.lua_CFunction wrapper = new KopiLua.Lua.lua_CFunction((new LuaMethodWrapper(translator, objType, methodName, bindingType)).call); translator.pushFunction(luaState, wrapper);
if (cachedMember == null) setMemberCache(memberCache, objType, methodName, wrapper); translator.push(luaState, true);
translator.pushFunction(luaState, wrapper); return 2;
translator.push(luaState, true); }
return 2; }
} else
} {
else // If we reach this point we found a static method, but can't use it in this context because the user passed in an instance
{ translator.throwError(luaState, "can't pass instance to static method " + methodName);
// If we reach this point we found a static method, but can't use it in this context because the user passed in an instance
translator.throwError(luaState, "can't pass instance to static method " + methodName); KopiLua.Lua.lua_pushnil(luaState);
}
KopiLua.Lua.lua_pushnil(luaState); }
} else
} {
else // kevinh - we want to throw an exception because meerly returning 'nil' in this case
{ // is not sufficient. valid data members may return nil and therefore there must be some
// kevinh - we want to throw an exception because meerly returning 'nil' in this case // way to know the member just doesn't exist.
// is not sufficient. valid data members may return nil and therefore there must be some
// way to know the member just doesn't exist. translator.throwError(luaState, "unknown member name " + methodName);
translator.throwError(luaState, "unknown member name " + methodName); KopiLua.Lua.lua_pushnil(luaState);
}
KopiLua.Lua.lua_pushnil(luaState);
} // push false because we are NOT returning a function (see luaIndexFunction)
translator.push(luaState, false);
// push false because we are NOT returning a function (see luaIndexFunction) return 2;
translator.push(luaState, false); }
return 2; /*
} * Checks if a MemberInfo object is cached, returning it or null.
/* */
* Checks if a MemberInfo object is cached, returning it or null. private object checkMemberCache(Hashtable memberCache, IReflect objType, string memberName)
*/ {
private object checkMemberCache(Hashtable memberCache, IReflect objType, string memberName) Hashtable members = (Hashtable)memberCache[objType];
{ if (members != null)
Hashtable members = (Hashtable)memberCache[objType]; return members[memberName];
if (members != null) else
return members[memberName]; return null;
else }
return null; /*
} * Stores a MemberInfo object in the member cache.
/* */
* Stores a MemberInfo object in the member cache. private void setMemberCache(Hashtable memberCache, IReflect objType, string memberName, object member)
*/ {
private void setMemberCache(Hashtable memberCache, IReflect objType, string memberName, object member) Hashtable members = (Hashtable)memberCache[objType];
{ if (members == null)
Hashtable members = (Hashtable)memberCache[objType]; {
if (members == null) members = new Hashtable();
{ memberCache[objType] = members;
members = new Hashtable(); }
memberCache[objType] = members; members[memberName] = member;
} }
members[memberName] = member; /*
} * __newindex metafunction of CLR objects. Receives the object,
/* * the member name and the value to be stored as arguments. Throws
* __newindex metafunction of CLR objects. Receives the object, * and error if the assignment is invalid.
* the member name and the value to be stored as arguments. Throws */
* and error if the assignment is invalid. private int setFieldOrProperty(KopiLua.Lua.lua_State luaState)
*/ {
private int setFieldOrProperty(KopiLua.Lua.lua_State luaState) object target = translator.getRawNetObject(luaState, 1);
{ if (target == null)
object target = translator.getRawNetObject(luaState, 1); {
if (target == null) translator.throwError(luaState, "trying to index and invalid object reference");
{ return 0;
translator.throwError(luaState, "trying to index and invalid object reference"); }
return 0; Type type = target.GetType();
}
Type type = target.GetType(); // First try to look up the parameter as a property name
string detailMessage;
// First try to look up the parameter as a property name bool didMember = trySetMember(luaState, type, target, BindingFlags.Instance, out detailMessage);
string detailMessage;
bool didMember = trySetMember(luaState, type, target, BindingFlags.Instance, out detailMessage); if (didMember)
return 0; // Must have found the property name
if (didMember)
return 0; // Must have found the property name // We didn't find a property name, now see if we can use a [] style this accessor to set array contents
try
// We didn't find a property name, now see if we can use a [] style this accessor to set array contents {
try if (type.IsArray && KopiLua.Lua.lua_isnumber(luaState, 2).ToBoolean())
{ {
if (type.IsArray && KopiLua.Lua.lua_isnumber(luaState, 2).ToBoolean()) int index = (int)KopiLua.Lua.lua_tonumber(luaState, 2);
{
int index = (int)KopiLua.Lua.lua_tonumber(luaState, 2); Array arr = (Array)target;
object val = translator.getAsType(luaState, 3, arr.GetType().GetElementType());
Array arr = (Array)target; arr.SetValue(val, index);
object val = translator.getAsType(luaState, 3, arr.GetType().GetElementType()); }
arr.SetValue(val, index); else
} {
else // Try to see if we have a this[] accessor
{ MethodInfo setter = type.GetMethod("set_Item");
// Try to see if we have a this[] accessor if (setter != null)
MethodInfo setter = type.GetMethod("set_Item"); {
if (setter != null) ParameterInfo[] args = setter.GetParameters();
{ Type valueType = args[1].ParameterType;
ParameterInfo[] args = setter.GetParameters();
Type valueType = args[1].ParameterType; // The new val ue the user specified
object val = translator.getAsType(luaState, 3, valueType);
// The new val ue the user specified
object val = translator.getAsType(luaState, 3, valueType); Type indexType = args[0].ParameterType;
object index = translator.getAsType(luaState, 2, indexType);
Type indexType = args[0].ParameterType;
object index = translator.getAsType(luaState, 2, indexType); object[] methodArgs = new object[2];
object[] methodArgs = new object[2]; // Just call the indexer - if out of bounds an exception will happen
methodArgs[0] = index;
// Just call the indexer - if out of bounds an exception will happen methodArgs[1] = val;
methodArgs[0] = index;
methodArgs[1] = val; setter.Invoke(target, methodArgs);
}
setter.Invoke(target, methodArgs); else
} {
else translator.throwError(luaState, detailMessage); // Pass the original message from trySetMember because it is probably best
{ }
translator.throwError(luaState, detailMessage); // Pass the original message from trySetMember because it is probably best }
} }
} catch (SEHException)
} {
catch (SEHException) // If we are seeing a C++ exception - this must actually be for Lua's private use. Let it handle it
{ throw;
// If we are seeing a C++ exception - this must actually be for Lua's private use. Let it handle it }
throw; catch (Exception e)
} {
catch (Exception e) ThrowError(luaState, e);
{ }
ThrowError(luaState, e); return 0;
} }
return 0;
} /// <summary>
/// Tries to set a named property or field
/// <summary> /// </summary>
/// Tries to set a named property or field /// <param name="luaState"></param>
/// </summary> /// <param name="targetType"></param>
/// <param name="luaState"></param> /// <param name="target"></param>
/// <param name="targetType"></param> /// <param name="bindingType"></param>
/// <param name="target"></param> /// <returns>false if unable to find the named member, true for success</returns>
/// <param name="bindingType"></param> private bool trySetMember(KopiLua.Lua.lua_State luaState, IReflect targetType, object target, BindingFlags bindingType, out string detailMessage)
/// <returns>false if unable to find the named member, true for success</returns> {
private bool trySetMember(KopiLua.Lua.lua_State luaState, IReflect targetType, object target, BindingFlags bindingType, out string detailMessage) detailMessage = null; // No error yet
{
detailMessage = null; // No error yet // If not already a string just return - we don't want to call tostring - which has the side effect of
// changing the lua typecode to string
// If not already a string just return - we don't want to call tostring - which has the side effect of // Note: We don't use isstring because the standard lua C isstring considers either strings or numbers to
// changing the lua typecode to string // be true for isstring.
// Note: We don't use isstring because the standard lua C isstring considers either strings or numbers to if (KopiLua.Lua.lua_type(luaState, 2).ToLuaType() != LuaType.String)
// be true for isstring. {
if (KopiLua.Lua.lua_type(luaState, 2).ToLuaType() != LuaType.String) detailMessage = "property names must be strings";
{ return false;
detailMessage = "property names must be strings"; }
return false;
} // We only look up property names by string
string fieldName = KopiLua.Lua.lua_tostring(luaState, 2).ToString();
// We only look up property names by string if (fieldName == null || fieldName.Length < 1 || !(char.IsLetter(fieldName[0]) || fieldName[0] == '_'))
string fieldName = KopiLua.Lua.lua_tostring(luaState, 2).ToString(); {
if (fieldName == null || fieldName.Length < 1 || !(char.IsLetter(fieldName[0]) || fieldName[0] == '_')) detailMessage = "invalid property name";
{ return false;
detailMessage = "invalid property name"; }
return false;
} // Find our member via reflection or the cache
MemberInfo member = (MemberInfo)checkMemberCache(memberCache, targetType, fieldName);
// Find our member via reflection or the cache if (member == null)
MemberInfo member = (MemberInfo)checkMemberCache(memberCache, targetType, fieldName); {
if (member == null) MemberInfo[] members = targetType.GetMember(fieldName, bindingType | BindingFlags.Public | BindingFlags.NonPublic);
{ if (members.Length > 0)
MemberInfo[] members = targetType.GetMember(fieldName, bindingType | BindingFlags.Public | BindingFlags.NonPublic); {
if (members.Length > 0) member = members[0];
{ setMemberCache(memberCache, targetType, fieldName, member);
member = members[0]; }
setMemberCache(memberCache, targetType, fieldName, member); else
} {
else detailMessage = "field or property '" + fieldName + "' does not exist";
{ return false;
detailMessage = "field or property '" + fieldName + "' does not exist"; }
return false; }
}
} if (member.MemberType == MemberTypes.Field)
{
if (member.MemberType == MemberTypes.Field) FieldInfo field = (FieldInfo)member;
{ object val = translator.getAsType(luaState, 3, field.FieldType);
FieldInfo field = (FieldInfo)member; try
object val = translator.getAsType(luaState, 3, field.FieldType); {
try field.SetValue(target, val);
{ }
field.SetValue(target, val); catch (Exception e)
} {
catch (Exception e) ThrowError(luaState, e);
{ }
ThrowError(luaState, e); // We did a call
} return true;
// We did a call }
return true; else if (member.MemberType == MemberTypes.Property)
} {
else if (member.MemberType == MemberTypes.Property) PropertyInfo property = (PropertyInfo)member;
{ object val = translator.getAsType(luaState, 3, property.PropertyType);
PropertyInfo property = (PropertyInfo)member; try
object val = translator.getAsType(luaState, 3, property.PropertyType); {
try property.SetValue(target, val, null);
{ }
property.SetValue(target, val, null); catch (Exception e)
} {
catch (Exception e) ThrowError(luaState, e);
{ }
ThrowError(luaState, e); // We did a call
} return true;
// We did a call }
return true;
} detailMessage = "'" + fieldName + "' is not a .net field or property";
return false;
detailMessage = "'" + fieldName + "' is not a .net field or property"; }
return false;
}
/*
* Writes to fields or properties, either static or instance. Throws an error
/* * if the operation is invalid.
* Writes to fields or properties, either static or instance. Throws an error */
* if the operation is invalid. private int setMember(KopiLua.Lua.lua_State luaState, IReflect targetType, object target, BindingFlags bindingType)
*/ {
private int setMember(KopiLua.Lua.lua_State luaState, IReflect targetType, object target, BindingFlags bindingType) string detail;
{ bool success = trySetMember(luaState, targetType, target, bindingType, out detail);
string detail;
bool success = trySetMember(luaState, targetType, target, bindingType, out detail); if(!success)
translator.throwError(luaState, detail);
if(!success)
translator.throwError(luaState, detail); return 0;
}
return 0;
} /// <summary>
/// Convert a C# exception into a Lua error
/// <summary> /// </summary>
/// Convert a C# exception into a Lua error /// <param name="e"></param>
/// </summary> /// We try to look into the exception to give the most meaningful description
/// <param name="e"></param> void ThrowError(KopiLua.Lua.lua_State luaState, Exception e)
/// We try to look into the exception to give the most meaningful description {
void ThrowError(KopiLua.Lua.lua_State luaState, Exception e) // If we got inside a reflection show what really happened
{ TargetInvocationException te = e as TargetInvocationException;
// If we got inside a reflection show what really happened
TargetInvocationException te = e as TargetInvocationException; if (te != null)
e = te.InnerException;
if (te != null)
e = te.InnerException; translator.throwError(luaState, e);
}
translator.throwError(luaState, e);
} /*
* __index metafunction of type references, works on static members.
/* */
* __index metafunction of type references, works on static members. private int getClassMethod(KopiLua.Lua.lua_State luaState)
*/ {
private int getClassMethod(KopiLua.Lua.lua_State luaState) IReflect klass;
{ object obj = translator.getRawNetObject(luaState, 1);
IReflect klass; if (obj == null || !(obj is IReflect))
object obj = translator.getRawNetObject(luaState, 1); {
if (obj == null || !(obj is IReflect)) translator.throwError(luaState, "trying to index an invalid type reference");
{ KopiLua.Lua.lua_pushnil(luaState);
translator.throwError(luaState, "trying to index an invalid type reference"); return 1;
KopiLua.Lua.lua_pushnil(luaState); }
return 1; else klass = (IReflect)obj;
} if (KopiLua.Lua.lua_isnumber(luaState, 2).ToBoolean())
else klass = (IReflect)obj; {
if (KopiLua.Lua.lua_isnumber(luaState, 2).ToBoolean()) int size = (int)KopiLua.Lua.lua_tonumber(luaState, 2);
{ translator.push(luaState, Array.CreateInstance(klass.UnderlyingSystemType, size));
int size = (int)KopiLua.Lua.lua_tonumber(luaState, 2); return 1;
translator.push(luaState, Array.CreateInstance(klass.UnderlyingSystemType, size)); }
return 1; else
} {
else string methodName = KopiLua.Lua.lua_tostring(luaState, 2).ToString();
{ if (methodName == null)
string methodName = KopiLua.Lua.lua_tostring(luaState, 2).ToString(); {
if (methodName == null) KopiLua.Lua.lua_pushnil(luaState);
{ return 1;
KopiLua.Lua.lua_pushnil(luaState); }
return 1; else return getMember(luaState, klass, null, methodName, BindingFlags.FlattenHierarchy | BindingFlags.Static);
} }
else return getMember(luaState, klass, null, methodName, BindingFlags.FlattenHierarchy | BindingFlags.Static); }
} /*
} * __newindex function of type references, works on static members.
/* */
* __newindex function of type references, works on static members. private int setClassFieldOrProperty(KopiLua.Lua.lua_State luaState)
*/ {
private int setClassFieldOrProperty(KopiLua.Lua.lua_State luaState) IReflect target;
{ object obj = translator.getRawNetObject(luaState, 1);
IReflect target; if (obj == null || !(obj is IReflect))
object obj = translator.getRawNetObject(luaState, 1); {
if (obj == null || !(obj is IReflect)) translator.throwError(luaState, "trying to index an invalid type reference");
{ return 0;
translator.throwError(luaState, "trying to index an invalid type reference"); }
return 0; else target = (IReflect)obj;
} return setMember(luaState, target, null, BindingFlags.FlattenHierarchy | BindingFlags.Static);
else target = (IReflect)obj; }
return setMember(luaState, target, null, BindingFlags.FlattenHierarchy | BindingFlags.Static); /*
} * __call metafunction of type references. Searches for and calls
/* * a constructor for the type. Returns nil if the constructor is not
* __call metafunction of type references. Searches for and calls * found or if the arguments are invalid. Throws an error if the constructor
* a constructor for the type. Returns nil if the constructor is not * generates an exception.
* found or if the arguments are invalid. Throws an error if the constructor */
* generates an exception. private int callConstructor(KopiLua.Lua.lua_State luaState)
*/ {
private int callConstructor(KopiLua.Lua.lua_State luaState) MethodCache validConstructor = new MethodCache();
{ IReflect klass;
MethodCache validConstructor = new MethodCache(); object obj = translator.getRawNetObject(luaState, 1);
IReflect klass; if (obj == null || !(obj is IReflect))
object obj = translator.getRawNetObject(luaState, 1); {
if (obj == null || !(obj is IReflect)) translator.throwError(luaState, "trying to call constructor on an invalid type reference");
{ KopiLua.Lua.lua_pushnil(luaState);
translator.throwError(luaState, "trying to call constructor on an invalid type reference"); return 1;
KopiLua.Lua.lua_pushnil(luaState); }
return 1; else klass = (IReflect)obj;
} KopiLua.Lua.lua_remove(luaState, 1);
else klass = (IReflect)obj; ConstructorInfo[] constructors = klass.UnderlyingSystemType.GetConstructors();
KopiLua.Lua.lua_remove(luaState, 1); foreach (ConstructorInfo constructor in constructors)
ConstructorInfo[] constructors = klass.UnderlyingSystemType.GetConstructors(); {
foreach (ConstructorInfo constructor in constructors) bool isConstructor = matchParameters(luaState, constructor, ref validConstructor);
{ if (isConstructor)
bool isConstructor = matchParameters(luaState, constructor, ref validConstructor); {
if (isConstructor) try
{ {
try translator.push(luaState, constructor.Invoke(validConstructor.args));
{ }
translator.push(luaState, constructor.Invoke(validConstructor.args)); catch (TargetInvocationException e)
} {
catch (TargetInvocationException e) ThrowError(luaState, e);
{ KopiLua.Lua.lua_pushnil(luaState);
ThrowError(luaState, e); }
KopiLua.Lua.lua_pushnil(luaState); catch
} {
catch KopiLua.Lua.lua_pushnil(luaState);
{ }
KopiLua.Lua.lua_pushnil(luaState); return 1;
} }
return 1; }
}
} string constructorName = (constructors.Length == 0) ? "unknown" : constructors[0].Name;
string constructorName = (constructors.Length == 0) ? "unknown" : constructors[0].Name; translator.throwError(luaState, String.Format("{0} does not contain constructor({1}) argument match",
klass.UnderlyingSystemType,
translator.throwError(luaState, String.Format("{0} does not contain constructor({1}) argument match", constructorName));
klass.UnderlyingSystemType, KopiLua.Lua.lua_pushnil(luaState);
constructorName)); return 1;
KopiLua.Lua.lua_pushnil(luaState); }
return 1; /*
} * Matches a method against its arguments in the Lua stack. Returns
/* * if the match was succesful. It it was also returns the information
* Matches a method against its arguments in the Lua stack. Returns * necessary to invoke the method.
* if the match was succesful. It it was also returns the information */
* necessary to invoke the method. internal bool matchParameters(KopiLua.Lua.lua_State luaState, MethodBase method, ref MethodCache methodCache)
*/ {
internal bool matchParameters(KopiLua.Lua.lua_State luaState, MethodBase method, ref MethodCache methodCache) ExtractValue extractValue;
{ bool isMethod = true;
ExtractValue extractValue; ParameterInfo[] paramInfo = method.GetParameters();
bool isMethod = true; int currentLuaParam = 1;
ParameterInfo[] paramInfo = method.GetParameters(); int nLuaParams = KopiLua.Lua.lua_gettop(luaState);
int currentLuaParam = 1; ArrayList paramList = new ArrayList();
int nLuaParams = KopiLua.Lua.lua_gettop(luaState); List<int> outList = new List<int>();
ArrayList paramList = new ArrayList(); List<MethodArgs> argTypes = new List<MethodArgs>();
List<int> outList = new List<int>(); foreach (ParameterInfo currentNetParam in paramInfo)
List<MethodArgs> argTypes = new List<MethodArgs>(); {
foreach (ParameterInfo currentNetParam in paramInfo) if (!currentNetParam.IsIn && currentNetParam.IsOut) // Skips out params
{ {
if (!currentNetParam.IsIn && currentNetParam.IsOut) // Skips out params outList.Add(paramList.Add(null));
{ }
outList.Add(paramList.Add(null)); else if (currentLuaParam > nLuaParams) // Adds optional parameters
} {
else if (currentLuaParam > nLuaParams) // Adds optional parameters if (currentNetParam.IsOptional)
{ {
if (currentNetParam.IsOptional) paramList.Add(currentNetParam.DefaultValue);
{ }
paramList.Add(currentNetParam.DefaultValue); else
} {
else isMethod = false;
{ break;
isMethod = false; }
break; }
} else if ((extractValue = translator.typeChecker.checkType(luaState, currentLuaParam, currentNetParam.ParameterType)) != null) // Type checking
} {
else if ((extractValue = translator.typeChecker.checkType(luaState, currentLuaParam, currentNetParam.ParameterType)) != null) // Type checking int index = paramList.Add(extractValue(luaState, currentLuaParam));
{ MethodArgs methodArg = new MethodArgs();
int index = paramList.Add(extractValue(luaState, currentLuaParam)); methodArg.index = index;
MethodArgs methodArg = new MethodArgs(); methodArg.extractValue = extractValue;
methodArg.index = index; argTypes.Add(methodArg);
methodArg.extractValue = extractValue; if (currentNetParam.ParameterType.IsByRef)
argTypes.Add(methodArg); outList.Add(index);
if (currentNetParam.ParameterType.IsByRef) currentLuaParam++;
outList.Add(index); } // Type does not match, ignore if the parameter is optional
currentLuaParam++; else if (currentNetParam.IsOptional)
} // Type does not match, ignore if the parameter is optional {
else if (currentNetParam.IsOptional) paramList.Add(currentNetParam.DefaultValue);
{ }
paramList.Add(currentNetParam.DefaultValue); else // No match
} {
else // No match isMethod = false;
{ break;
isMethod = false; }
break; }
} if (currentLuaParam != nLuaParams + 1) // Number of parameters does not match
}
if (currentLuaParam != nLuaParams + 1) // Number of parameters does not match
isMethod = false; isMethod = false;
if (isMethod) if (isMethod)
{ {
methodCache.args = paramList.ToArray(); methodCache.args = paramList.ToArray();
methodCache.cachedMethod = method; methodCache.cachedMethod = method;
methodCache.outList = outList.ToArray(); methodCache.outList = outList.ToArray();
methodCache.argTypes = argTypes.ToArray(); methodCache.argTypes = argTypes.ToArray();
} }
return isMethod; return isMethod;
} }
} }
} }
\ No newline at end of file
...@@ -106,13 +106,15 @@ namespace LuaInterface ...@@ -106,13 +106,15 @@ namespace LuaInterface
object targetObject=target; object targetObject=target;
bool failedCall=true; bool failedCall=true;
int nReturnValues=0; int nReturnValues=0;
Console.WriteLine("asyyyyyyyyyyyyyy");
if(!KopiLua.Lua.lua_checkstack(luaState,5).ToBoolean()) if(!KopiLua.Lua.lua_checkstack(luaState,5).ToBoolean())
throw new LuaException("Lua stack overflow"); throw new LuaException("Lua stack overflow");
Console.WriteLine("asyyyyyyyyyyyyyy1");
bool isStatic = (bindingType & BindingFlags.Static) == BindingFlags.Static; bool isStatic = (bindingType & BindingFlags.Static) == BindingFlags.Static;
Console.WriteLine("asyyyyyyyyyyyyyy2");
SetPendingException(null); SetPendingException(null);
Console.WriteLine("asyyyyyyyyyyyyyy3");
Console.WriteLine(methodToCall==null);
if(methodToCall==null) // Method from name if(methodToCall==null) // Method from name
{ {
if (isStatic) if (isStatic)
...@@ -120,6 +122,9 @@ namespace LuaInterface ...@@ -120,6 +122,9 @@ namespace LuaInterface
else else
targetObject=extractTarget(luaState,1); targetObject=extractTarget(luaState,1);
//KopiLua.Lua.lua_remove(luaState,1); // Pops the receiver //KopiLua.Lua.lua_remove(luaState,1); // Pops the receiver
Console.WriteLine("asdxxxxxx");
Console.WriteLine(lastCalledMethod.cachedMethod);
Console.WriteLine(lastCalledMethod.cachedMethod!=null);
if(lastCalledMethod.cachedMethod!=null) // Cached? if(lastCalledMethod.cachedMethod!=null) // Cached?
{ {
int numStackToSkip = isStatic ? 0 : 1; // If this is an instance invoe we will have an extra arg on the stack for the targetObject int numStackToSkip = isStatic ? 0 : 1; // If this is an instance invoe we will have an extra arg on the stack for the targetObject
...@@ -131,6 +136,8 @@ namespace LuaInterface ...@@ -131,6 +136,8 @@ namespace LuaInterface
throw new LuaException("Lua stack overflow"); throw new LuaException("Lua stack overflow");
try try
{ {
Console.WriteLine("0");
Console.WriteLine(lastCalledMethod.argTypes.Length);
for(int i=0;i<lastCalledMethod.argTypes.Length;i++) for(int i=0;i<lastCalledMethod.argTypes.Length;i++)
{ {
lastCalledMethod.args[lastCalledMethod.argTypes[i].index]= lastCalledMethod.args[lastCalledMethod.argTypes[i].index]=
...@@ -142,12 +149,14 @@ namespace LuaInterface ...@@ -142,12 +149,14 @@ namespace LuaInterface
throw new LuaException("argument number "+(i+1)+" is invalid"); throw new LuaException("argument number "+(i+1)+" is invalid");
} }
} }
Console.WriteLine("asd");
if((bindingType & BindingFlags.Static)==BindingFlags.Static) if((bindingType & BindingFlags.Static)==BindingFlags.Static)
{ {
translator.push(luaState,lastCalledMethod.cachedMethod.Invoke(null,lastCalledMethod.args)); translator.push(luaState,lastCalledMethod.cachedMethod.Invoke(null,lastCalledMethod.args));
} }
else else
{ {
Console.WriteLine("asd2");
if(lastCalledMethod.cachedMethod.IsConstructor) if(lastCalledMethod.cachedMethod.IsConstructor)
translator.push(luaState,((ConstructorInfo)lastCalledMethod.cachedMethod).Invoke(lastCalledMethod.args)); translator.push(luaState,((ConstructorInfo)lastCalledMethod.cachedMethod).Invoke(lastCalledMethod.args));
else else
......
...@@ -618,6 +618,7 @@ namespace LuaInterface ...@@ -618,6 +618,7 @@ namespace LuaInterface
if(udata!=-1) if(udata!=-1)
return objects[udata]; return objects[udata];
else else
//return null;
return getUserData(luaState,index); return getUserData(luaState,index);
} }
default: default:
...@@ -749,7 +750,6 @@ namespace LuaInterface ...@@ -749,7 +750,6 @@ namespace LuaInterface
{ {
// Make sure we are _really_ ILuaGenerated // Make sure we are _really_ ILuaGenerated
Type typ = o.GetType(); Type typ = o.GetType();
return (typ.GetInterface("ILuaGeneratedType") != null); return (typ.GetInterface("ILuaGeneratedType") != null);
} }
else else
......
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