Improve varargs handlnig in luajava bindings.

This commit is contained in:
James Roseborough
2010-05-22 17:47:31 +00:00
parent a65110df88
commit f146268c47
3 changed files with 58 additions and 76 deletions

View File

@@ -36,7 +36,7 @@ public class CoerceJavaToLua {
public LuaValue coerce( Object javaValue );
};
private static Map COERCIONS = new HashMap();
static final Map COERCIONS = new HashMap();
static {
Coercion boolCoercion = new Coercion() {

View File

@@ -37,8 +37,7 @@ public class CoerceLuaToJava {
public int score( int paramType );
};
private static Map COERCIONS = new HashMap();
private static Coercion OBJECT_COERCION;
static final Map COERCIONS = new HashMap();
static {
Coercion boolCoercion = new Coercion() {
@@ -232,7 +231,7 @@ public class CoerceLuaToJava {
/** Score a single parameter, including array handling */
private static int scoreParam(int paramType, Class c) {
static int scoreParam(int paramType, Class c) {
if ( paramType == LuaValue.TUSERDATA && !c.isArray() )
return 0;
Coercion co = (Coercion) COERCIONS.get( c );
@@ -277,11 +276,23 @@ public class CoerceLuaToJava {
throw new LuaError("no coercion found for "+a.getClass()+" to "+c);
}
static Object[] coerceArgs(Varargs suppliedArgs, Class[] parameterTypes) {
static Object[] coerceArgs(Varargs suppliedArgs, Class[] parameterTypes, boolean isvarargs) {
int nsupplied = suppliedArgs.narg();
int n = parameterTypes.length;
int nplain = Math.min(isvarargs? n-1: n, nsupplied);
Object[] args = new Object[n];
for ( int i=0; i<n; i++ )
for ( int i=0; i<nplain; i++ )
args[i] = coerceArg( suppliedArgs.arg(i+1), parameterTypes[i] );
if ( isvarargs ) {
int nvar = Math.max(0, nsupplied - nplain);
Class typevar = parameterTypes[n-1].getComponentType();
Object array = Array.newInstance(typevar, nvar);
for ( int index=0; index<nvar; index++ ) {
Object value = coerceArg( suppliedArgs.arg(nplain+index+1), typevar );
Array.set(array, index, value);
}
args[n-1] = array;
}
return args;
}

View File

@@ -43,8 +43,6 @@ import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaUserdata;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Varargs;
import org.luaj.vm2.lib.BaseLib;
import org.luaj.vm2.lib.OneArgFunction;
import org.luaj.vm2.lib.PackageLib;
import org.luaj.vm2.lib.ThreeArgFunction;
import org.luaj.vm2.lib.TwoArgFunction;
@@ -52,14 +50,14 @@ import org.luaj.vm2.lib.VarArgFunction;
public class LuajavaLib extends VarArgFunction {
private static final int INIT = 0;
private static final int BINDCLASS = 1;
private static final int NEWINSTANCE = 2;
private static final int NEW = 3;
private static final int CREATEPROXY = 4;
private static final int LOADLIB = 5;
static final int INIT = 0;
static final int BINDCLASS = 1;
static final int NEWINSTANCE = 2;
static final int NEW = 3;
static final int CREATEPROXY = 4;
static final int LOADLIB = 5;
private static final String[] NAMES = {
static final String[] NAMES = {
"bindClass",
"newInstance",
"new",
@@ -67,12 +65,17 @@ public class LuajavaLib extends VarArgFunction {
"loadLib",
};
private static final Map classMetatables = new HashMap();
static final Map classMetatables = new HashMap();
private static final int METHOD_MODIFIERS_VARARGS = 0x80;
static final int METHOD_MODIFIERS_VARARGS = 0x80;
private static LuaValue LENGTH = valueOf("length");
static final LuaValue LENGTH = valueOf("length");
static final Map consCache = new HashMap();
static final Map consIndex = new HashMap();
static final Map methCache = new HashMap();
static final Map methIndex = new HashMap();
public LuajavaLib() {
}
@@ -98,10 +101,11 @@ public class LuajavaLib extends VarArgFunction {
final Varargs consargs = args.subargs(2);
final long paramssig = LuajavaLib.paramsSignatureOf( consargs );
final Constructor con = resolveConstructor( clazz, paramssig );
final boolean isvarargs = ((con.getModifiers() & METHOD_MODIFIERS_VARARGS) != 0);
// coerce args, construct instance
Object[] cargs = CoerceLuaToJava.coerceArgs( consargs, con.getParameterTypes() );
Object o = con.newInstance( cargs );
final Object[] cargs = CoerceLuaToJava.coerceArgs( consargs, con.getParameterTypes(), isvarargs );
final Object o = con.newInstance( cargs );
// return result
return toUserdata( o, clazz );
@@ -306,7 +310,7 @@ public class LuajavaLib extends VarArgFunction {
return LuaValue.userdataOf(instance,mt);
}
private static final class LMethod extends VarArgFunction {
static final class LMethod extends VarArgFunction {
private final Class clazz;
private final String s;
private LMethod(Class clazz, String s) {
@@ -319,14 +323,15 @@ public class LuajavaLib extends VarArgFunction {
public Varargs invoke(Varargs args) {
try {
// find the method
Object instance = args.touserdata(1);
Varargs methargs = args.subargs(2);
long paramssig = LuajavaLib.paramsSignatureOf(methargs);
Method meth = resolveMethod( clazz, s, paramssig );
final Object instance = args.touserdata(1);
final Varargs methargs = args.subargs(2);
final long paramssig = LuajavaLib.paramsSignatureOf(methargs);
final Method meth = resolveMethod( clazz, s, paramssig );
final boolean isvarargs = ((meth.getModifiers() & METHOD_MODIFIERS_VARARGS) != 0);
// coerce the arguments
Object[] margs = CoerceLuaToJava.coerceArgs( methargs, meth.getParameterTypes() );
Object result = meth.invoke( instance, margs );
final Object[] margs = CoerceLuaToJava.coerceArgs( methargs, meth.getParameterTypes(), isvarargs );
final Object result = meth.invoke( instance, margs );
// coerce the result
return CoerceJavaToLua.coerce(result);
@@ -338,13 +343,7 @@ public class LuajavaLib extends VarArgFunction {
}
}
private static Map consCache =
new HashMap();
private static Map consIndex =
new HashMap();
private static Constructor resolveConstructor(Class clazz, long paramssig ) {
static Constructor resolveConstructor(Class clazz, long paramssig ) {
// get the cache
Map cache = (Map) consCache.get( clazz );
@@ -357,31 +356,18 @@ public class LuajavaLib extends VarArgFunction {
return c;
// get index
Map index = (Map) consIndex.get( clazz );
if ( index == null ) {
consIndex.put( clazz, index = new HashMap() );
Constructor[] cons = clazz.getConstructors();
for ( int i=0; i<cons.length; i++ ) {
Constructor con = cons[i];
Integer n = new Integer( con.getParameterTypes().length );
List list = (List) index.get(n);
if ( list == null )
index.put( n, list = new ArrayList() );
list.add( con );
}
Constructor[] cons = (Constructor[]) consIndex.get( clazz );
if ( cons == null ) {
consIndex.put( clazz, cons = clazz.getConstructors() );
if ( cons == null )
throw new IllegalArgumentException("no public constructors");
}
// figure out best list of arguments == supplied args
Integer n = new Integer( LuajavaLib.paramsCountFromSig(paramssig) );
List list = (List) index.get(n);
if ( list == null )
throw new IllegalArgumentException("no constructor with "+n+" args");
// find constructor with best score
int bests = Integer.MAX_VALUE;
int besti = 0;
for ( int i=0, size=list.size(); i<size; i++ ) {
Constructor con = (Constructor) list.get(i);
for ( int i=0, size=cons.length; i<size; i++ ) {
Constructor con = cons[i];
int paramType = LuajavaLib.paramTypeFromSig(paramssig, 0);
int s = CoerceLuaToJava.scoreParamTypes(paramType, con.getParameterTypes());
if ( s < bests ) {
@@ -391,19 +377,12 @@ public class LuajavaLib extends VarArgFunction {
}
// put into cache
c = (Constructor) list.get(besti);
c = cons[besti];
cache.put( paramssig, c );
return c;
}
private static Map methCache =
new HashMap();
private static Map methIndex =
new HashMap();
private static Method resolveMethod(Class clazz, String methodName, long paramssig ) {
static Method resolveMethod(Class clazz, String methodName, long paramssig ) {
// get the cache
Map nameCache = (Map) methCache.get( clazz );
@@ -426,27 +405,19 @@ public class LuajavaLib extends VarArgFunction {
for ( int i=0; i<meths.length; i++ ) {
Method meth = meths[i];
String s = meth.getName();
Integer n = new Integer(meth.getParameterTypes().length);
Map map = (Map) index.get(s);
if ( map == null )
index.put( s, map = new HashMap() );
List list = (List) map.get(n);
List list = (List) index.get(s);
if ( list == null )
map.put( n, list = new ArrayList() );
index.put( s, list = new ArrayList() );
list.add( meth );
}
}
// figure out best list of arguments == supplied args
Map map = (Map) index.get(methodName);
if ( map == null )
throw new IllegalArgumentException("no method named '"+methodName+"'");
Integer n = new Integer( LuajavaLib.paramsCountFromSig( paramssig ) );
List list = (List) map.get(n);
List list = (List) index.get(methodName);
if ( list == null )
throw new IllegalArgumentException("no method named '"+methodName+"' with "+n+" args");
throw new IllegalArgumentException("no method named '"+methodName+"'");
// find constructor with best score
// find method with best score
int bests = Integer.MAX_VALUE;
int besti = 0;
for ( int i=0, size=list.size(); i<size; i++ ) {