1 -LuaJava是什么以及LuaJava特点
LuaJava is a scripting tool for Java. The goal of this tool is to allow scripts written in Lua to manipulate components developed in Java.
LuaJava allows Java components to be accessed from Lua using the same syntax that is used for accessing Lua`s native objects, without any need for declarations or any kind of preprocessing.
LuaJava also allows Java to implement an interface using Lua. This way any interface can be implemented in Lua and passed as parameter to any method, and when called, the equivalent function will be called in Lua, and it's result passed back to Java.
LuaJava是java语言的一个脚本工具. 目标是在Java允许通过编写java脚本来操作组件.
LuaJava允许不需要预先声明或者其他任何的预处理来相互方法. Lua语法来访问java组件,也可以是java来访问Lua语言中的对象
2- LuaJava历史
LuaJava 1.1
LuaJava 1.1 was developed by Thiago Ponte.
LuaJava 1.0
LuaJava 1.0 was developed by Thiago Ponte and sponsored by Ideais, Fábrica Digital, Finep and CNPq.
LuaJava 1.0 beta
LuaJava 1.0 beta was reimplemented to be compatible with Lua 5.0 and with new features of Java 1.3. LuaJava 1.0 beta was developed by Thiago Ponte and Rafael Rizzato with contributions from João Machado, Danilo Tuler and Roberto Ierusalimschy.
LuaJava for Lua 3.1
LuaJava was first developed by Carlos Cassino.
LuaJava项目由Carlos Cassino 创建,但是主要贡献者 为Thiago Ponte .
3- LuaJava版本更新
1.1 [24/Jan/2007]changes to comply with Lua 5.1 API;
included LUA_MULTRET as a LuaState constant;
corrected bug on LuaObject.call on the order of the results.
1.0 [22/Jun/2005]
improved error handling;
dropped JDK 1.3 compatibility;
windows binaries compatible with LuaBinaries 5.0.2 Release 2;
new documentation format.
1.0 Beta 4 [21/Jan/2005]
package renamed to "org.keplerproject.luajava";
LuaObject.getLuaState is now public;
new function LuaObject.type();
JavaFunction.foo() renamed to JavaFunction.execute();
method called by javaLoadLib now can return an int.
1.0 Beta 3 [21/Sep/2004]
new function in lua luajava.loadLib, that opens libraries for Lua written in Java;
function LuaState.setGlobal now receives String, to work like Lua setglobal;
JavaFunction.foo() throws LuaException;
new function LuaState.pushString(byte[]);
Bugs linking some lua functions to Java;
minor bug fixes.
1.0 Beta 2 [07/Jul/2004]
now supports multi-threading;
new function LuaState.close() that should be called to close the state;
LuaState was missing some functions;
many bug fixes.
1.0 Beta 1 [28/Jun/2004] LuaJava version 1.1 uses LuaBinaries 5.1.1 and Java JDK 1.4 or above.
Lua语言的主要版本在2004年开始,Java语言2007年已经发布 Java SE 6.0 (1.6.0)版本,对于Lua5.1.1是Lua最重要的一个大版本更新,Lua语言特性基本囊括完全。java版本1.6.0也提供了较完全的特性。
4 LuaJava中的C语言代码
在LuaJava中包括了一个luajava.c文件。 luajava.c module is the implementation of luajava's dinamic library.
In this module lua's functions are exported to be used in java by jni,
and also the functions that will be used and exported to lua so that
Java Objects' functions can be called.
LuaJava.c文件模块主要实现luajava的动态链接库。
在C文件中,lua 语言脚本函数可以使java语言通过Java Native Interface技术来实现访问。
同时,Lua 可以调用Java 对象的函数。
2- LuaJava 中关键的Java源代码
CPtr 类,用来抽象C语言中指针。
/**
* An abstraction for a C pointer data type. A CPtr instance represents, on
* the Java side, a C pointer. The C pointer could be any <em>type</em> of C
* pointer.
*/
//对于C 指针数据类型的一种抽象,一个CPtr可以用来在java语言中表示C指针。C指针可以是任何类型的
public class CPtr
{
public boolean equals(Object other)
{
if (other == null)
return false;
if (other == this)
return true;
if (CPtr.class != other.getClass())
return false;
return peer == ((CPtr)other).peer;
}
/* Pointer value of the real C pointer. Use long to be 64-bit safe. */
private long peer;
protected long getPeer()
{
return peer;
}
CPtr() {}
}
LuaState.java 关键类的主要源代码
-
public class LuaState extends java.lang.Object {}
/**
* LuaState if the main class of LuaJava for the Java developer.
* LuaState is a mapping of most of Lua's C API functions.
* LuaState also provides many other functions that will be used to manipulate
* objects between Lua and Java.
* @author Thiago Ponte
*/
//LuaState 是java编程人员主要操作的类.LuaState是Lua C API 函数的映射类. LuaState 同样提供了很多方法可以操作Lua 和Java对象.
//LuaState java类与luajava.c文件相对应。这两个文件的主要功能:
//1 -通过luajava.c文件来使用Lua语言提供的功能
//2 -LuaState.java文件通过Java Native interface 技术把Lua C API 映射成 Lua Java API
//这样就可以通过Java语言来提供 Java和Lua语言交互的功能。(对象相互使用,方法相互调用,对象生命周期管理等)
//3-LuaState同时也建立了与LuaJava.c文件的关联
public class LuaState
{
private final static String LUAJAVA_LIB = "luajava-1.1"; //定义dll动态类库的名称
final public static Integer LUA_GLOBALSINDEX = new Integer(-10002);
final public static Integer LUA_REGISTRYINDEX = new Integer(-10000);
final public static Integer LUA_TNONE = new Integer(-1);
final public static Integer LUA_TNIL = new Integer(0);
final public static Integer LUA_TBOOLEAN = new Integer(1);
final public static Integer LUA_TLIGHTUSERDATA = new Integer(2);
final public static Integer LUA_TNUMBER = new Integer(3);
final public static Integer LUA_TSTRING = new Integer(4);
final public static Integer LUA_TTABLE = new Integer(5);
final public static Integer LUA_TFUNCTION = new Integer(6);
final public static Integer LUA_TUSERDATA = new Integer(7);
final public static Integer LUA_TTHREAD = new Integer(8);
/**
* Specifies that an unspecified (multiple) number of return arguments
* will be returned by a call.
*/
final public static Integer LUA_MULTRET = new Integer(-1);
/*
* error codes for `lua_load' and `lua_pcall'
*/
/**
* a runtime error.
*/
final public static Integer LUA_ERRRUN = new Integer(1);
/**
*
*/
final public static Integer LUA_YIELD = new Integer(2);
/**
* syntax error during pre-compilation.
*/
final public static Integer LUA_ERRSYNTAX = new Integer(3);
/**
* memory allocation error. For such errors, Lua does not call
* the error handler function.
*/
final public static Integer LUA_ERRMEM = new Integer(4);
/**
* error while running the error handler function.
*/
final public static Integer LUA_ERRERR = new Integer(5);
/**
* Opens the library containing the luajava API
*/
static
{
System.loadLibrary(LUAJAVA_LIB);
}
private CPtr luaState;
private int stateId;
/**
* Constructor to instance a new LuaState and initialize it with LuaJava's functions
* @param stateId
*/
protected LuaState(int stateId)
{
luaState = _open();
luajava_open(luaState, stateId);
this.stateId = stateId;
}
/**
* Receives a existing state and initializes it
* @param luaState
*/
protected LuaState(CPtr luaState)
{
this.luaState = luaState;
this.stateId = LuaStateFactory.insertLuaState(this);
luajava_open(luaState, stateId);
}
/********************* Lua Native Interface *************************/
private synchronized native CPtr _open();
private synchronized native void _close(CPtr ptr);
private synchronized native CPtr _newthread(CPtr ptr);
// Stack manipulation
private synchronized native int _getTop(CPtr ptr);
private synchronized native void _setTop(CPtr ptr, int idx);
private synchronized native void _pushValue(CPtr ptr, int idx);
private synchronized native void _remove(CPtr ptr, int idx);
private synchronized native void _insert(CPtr ptr, int idx);
private synchronized native void _replace(CPtr ptr, int idx);
private synchronized native int _checkStack(CPtr ptr, int sz);
private synchronized native void _xmove(CPtr from, CPtr to, int n);
// Access functions
private synchronized native int _isNumber(CPtr ptr, int idx);
private synchronized native int _isString(CPtr ptr, int idx);
private synchronized native int _isCFunction(CPtr ptr, int idx);
private synchronized native int _isUserdata(CPtr ptr, int idx);
private synchronized native int _type(CPtr ptr, int idx);
private synchronized native String _typeName(CPtr ptr, int tp);
private synchronized native int _equal(CPtr ptr, int idx1, int idx2);
private synchronized native int _rawequal(CPtr ptr, int idx1, int idx2);
private synchronized native int _lessthan(CPtr ptr, int idx1, int idx2);
private synchronized native double _toNumber(CPtr ptr, int idx);
private synchronized native int _toInteger(CPtr ptr, int idx);
private synchronized native int _toBoolean(CPtr ptr, int idx);
private synchronized native String _toString(CPtr ptr, int idx);
private synchronized native int _objlen(CPtr ptr, int idx);
private synchronized native CPtr _toThread(CPtr ptr, int idx);
// Push functions
private synchronized native void _pushNil(CPtr ptr);
private synchronized native void _pushNumber(CPtr ptr, double number);
private synchronized native void _pushInteger(CPtr ptr, int integer);
private synchronized native void _pushString(CPtr ptr, String str);
private synchronized native void _pushString(CPtr ptr, byte[] bytes, int n);
private synchronized native void _pushBoolean(CPtr ptr, int bool);
// Get functions
private synchronized native void _getTable(CPtr ptr, int idx);
private synchronized native void _getField(CPtr ptr, int idx, String k);
private synchronized native void _rawGet(CPtr ptr, int idx);
private synchronized native void _rawGetI(CPtr ptr, int idx, int n);
private synchronized native void _createTable(CPtr ptr, int narr, int nrec);
private synchronized native int _getMetaTable(CPtr ptr, int idx);
private synchronized native void _getFEnv(CPtr ptr, int idx);
// Set functions
private synchronized native void _setTable(CPtr ptr, int idx);
private synchronized native void _setField(CPtr ptr, int idx, String k);
private synchronized native void _rawSet(CPtr ptr, int idx);
private synchronized native void _rawSetI(CPtr ptr, int idx, int n);
private synchronized native int _setMetaTable(CPtr ptr, int idx);
private synchronized native int _setFEnv(CPtr ptr, int idx);
private synchronized native void _call(CPtr ptr, int nArgs, int nResults);
private synchronized native int _pcall(CPtr ptr, int nArgs, int Results, int errFunc);
// Coroutine Functions
private synchronized native int _yield(CPtr ptr, int nResults);
private synchronized native int _resume(CPtr ptr, int nargs);
private synchronized native int _status(CPtr ptr);
// Gargabe Collection Functions
final public static Integer LUA_GCSTOP = new Integer(0);
final public static Integer LUA_GCRESTART = new Integer(1);
final public static Integer LUA_GCCOLLECT = new Integer(2);
final public static Integer LUA_GCCOUNT = new Integer(3);
final public static Integer LUA_GCCOUNTB = new Integer(4);
final public static Integer LUA_GCSTEP = new Integer(5);
final public static Integer LUA_GCSETPAUSE = new Integer(6);
final public static Integer LUA_GCSETSTEPMUL = new Integer(7);
private synchronized native int _gc(CPtr ptr, int what, int data);
// Miscellaneous Functions
private synchronized native int _error(CPtr ptr);
private synchronized native int _next(CPtr ptr, int idx);
private synchronized native void _concat(CPtr ptr, int n);
// Some macros
private synchronized native void _pop(CPtr ptr, int n);
private synchronized native void _newTable(CPtr ptr);
private synchronized native int _strlen(CPtr ptr, int idx);
private synchronized native int _isFunction(CPtr ptr, int idx);
private synchronized native int _isTable(CPtr ptr, int idx);
private synchronized native int _isNil(CPtr ptr, int idx);
private synchronized native int _isBoolean(CPtr ptr, int idx);
private synchronized native int _isThread(CPtr ptr, int idx);
private synchronized native int _isNone(CPtr ptr, int idx);
private synchronized native int _isNoneOrNil(CPtr ptr, int idx);
private synchronized native void _setGlobal(CPtr ptr, String name);
private synchronized native void _getGlobal(CPtr ptr, String name);
private synchronized native int _getGcCount(CPtr ptr);
// LuaLibAux
private synchronized native int _LdoFile(CPtr ptr, String fileName);
private synchronized native int _LdoString(CPtr ptr, String string);
//private synchronized native int _doBuffer(CPtr ptr, byte[] buff, long sz, String n);
private synchronized native int _LgetMetaField(CPtr ptr, int obj, String e);
private synchronized native int _LcallMeta(CPtr ptr, int obj, String e);
private synchronized native int _Ltyperror(CPtr ptr, int nArg, String tName);
private synchronized native int _LargError(CPtr ptr, int numArg, String extraMsg);
private synchronized native String _LcheckString(CPtr ptr, int numArg);
private synchronized native String _LoptString(CPtr ptr, int numArg, String def);
private synchronized native double _LcheckNumber(CPtr ptr, int numArg);
private synchronized native double _LoptNumber(CPtr ptr, int numArg, double def);
private synchronized native int _LcheckInteger(CPtr ptr, int numArg);
private synchronized native int _LoptInteger(CPtr ptr, int numArg, int def);
private synchronized native void _LcheckStack(CPtr ptr, int sz, String msg);
private synchronized native void _LcheckType(CPtr ptr, int nArg, int t);
private synchronized native void _LcheckAny(CPtr ptr, int nArg);
private synchronized native int _LnewMetatable(CPtr ptr, String tName);
private synchronized native void _LgetMetatable(CPtr ptr, String tName);
private synchronized native void _Lwhere(CPtr ptr, int lvl);
private synchronized native int _Lref(CPtr ptr, int t);
private synchronized native void _LunRef(CPtr ptr, int t, int ref);
private synchronized native int _LgetN(CPtr ptr, int t);
private synchronized native void _LsetN(CPtr ptr, int t, int n);
private synchronized native int _LloadFile(CPtr ptr, String fileName);
private synchronized native int _LloadBuffer(CPtr ptr, byte[] buff, long sz, String name);
private synchronized native int _LloadString(CPtr ptr, String s);
private synchronized native String _Lgsub(CPtr ptr, String s, String p, String r);
private synchronized native String _LfindTable(CPtr ptr, int idx, String fname, int szhint);
private synchronized native void _openBase(CPtr ptr);
private synchronized native void _openTable(CPtr ptr);
private synchronized native void _openIo(CPtr ptr);
private synchronized native void _openOs(CPtr ptr);
private synchronized native void _openString(CPtr ptr);
private synchronized native void _openMath(CPtr ptr);
private synchronized native void _openDebug(CPtr ptr);
private synchronized native void _openPackage(CPtr ptr);
private synchronized native void _openLibs(CPtr ptr);
}
public class LuaObject extends java.lang.Object {}
This class represents a Lua object of any type. A LuaObject is constructed by a LuaState object using one of the four methods:
•LuaState.getLuaObject(String globalName)
•LuaState.getLuaObject(LuaObject parent, String name)
•LuaState.getLuaObject(LuaObject parent, Number name)
•LuaState.getLuaObject(LuaObject parent, LuaObject name)
•LuaState.getLuaObject(int index)
The LuaObject will represent only the object itself, not a variable or a stack index, so when you change a string, remember that strings are immutable objects in Lua, and the LuaObject you have will represent the old one.
LuaJava allows you to implement a class in Lua, like said before. If you want to create this proxy from Java, you should have a LuaObject representing the table that has the functions that implement the interface.
From this LuaObject you can call the createProxy(String implements)
. This method receives the string with the name of the interfaces implemented by the object separated by comma.
LuaObject类是LuaJava的核心。如下内容节选自:LuaJava-A Scripting Tool for Java的论文部分章节。
The Implementation of LuaJava
Because Lua and Java have quite different run time behaviors, we have used different techniques to implement the Lua proxies and the Java proxies.
LuaJava是通过代理来实现的:当Java 对象传递到Lua语言中,一个Lua Object对象将创建来表示java对象。
A fallback, in Lua, is a function that can be used to modify the default behavior of the language for some events.
This access triggers a fallback; the fallback, having access to the proxy (and thus to the Java
object it represents) and the method name, uses Java’s reflexive API to obtain information about that method (or methods, since Java allows overloading).
each new method, when called, first checks whether the corresponding method in Lua exist.
However, if the Lua object has no such method, the subclass method detects this absence, and calls instead itssuper implementation, that is, the method from the original class.
only the methods that will be used. Moreover, we can add methods to ourobject incrementally, even after it has been passed to Java.