LuaJava:LuaJava 初探

 

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


LuaJava is implemented throughproxies:

whenever a Java object is passed to Lua, a Lua object is created to represent it. 
Conversely, when a Lua object is passed to Java, a Java object is used to represent it.
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对象。
反过来,当一个Lua对象传递到Java语言中,一个java对象将创建处理用来表示Lua对象。
因为Lua和java语言有着不同的运行时行为,所以使用不同的技术来实现Lua代理和java代理。

A Lua proxy (that is, a Lua object that represents a Java object) is implemented using the fallback mechanism
A fallback, in Lua, is a function that can be used to modify the default behavior of the language for some events.
In LuaJava we use fallbacks to modify the way proxy fields are accessed and modified. 
So, a proxy is a nearly empty Lua object that intercepts any access to its (usually empty) fields.
A proxy has also at least one non empty field, that stores a reference to the Java object it represents.

 

Above shows what happens when we call a proxy’s method: 
The first step, shown in the solid box, is the access to a field called move.

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).
The fallback then returns aclosure with this information.

The second step, shown in the dashed box, is triggered when the closure is applied to the given arguments.
At this point the closure selects a method suited to the actual parameters, converts them from Lua to Java, executes the actual invocation, and converts back the result, if there is one.
As a performance improvement, at the end of the invocation a closure with the selected method is stored in field move of the proxy.
Therefore, in the following calls the first step can be avoided.
This same algorithm, with small modifications, is used to access instance  variables and array elements.
Similarly, the fallback over field modifications is used to handle assignments to array elements and instance variables.


The implementation of Java proxies for Lua objects is a little more complex.
As Java has type declarations, each Java proxy must have a predefined type. Moreover, because Java is statically typed, we must have a class for each type of proxy that we create. LuaJava builds these classes on demand.First, it writes the class bytecode in a byte array, Next, it uses a ClassLoader to dynamically load this new class into the program.
A Java type can be an interface or a class. The proxies for these two kinds  of types are slightly different.
In both cases, the proxy has an instance variable with a reference to the Lua object it represents.

For a proxy that implements an interface, LuaJava create a new class, compatible with the given interface,with all its methods coded as follows: 
First, they convert their arguments to  Lua;
        next, they call the corresponding method in the Lua object;  
        Finally, they  convert eventual results back to Java.
When the proxy represents a class, LuaJava implements it as a subclass of the original class.
This subclass redefines all the original methods;
each new method, when called, first checks whether the corresponding method in Lua exist. 
If the Lua method is present, it is called, like in the case of interfaces.

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. 
In this way, a Lua object implementing a class “inherits” from the class any method that it does not redefine.



A Lua object representing a Java interface does not need to implementall its methods, quite the opposite.
After all, one of the goals of a scriptinglanguage is to allow rapid prototyping. With LuaJava, we need to implement
only the methods that will be used. Moreover, we can add methods to ourobject incrementally, even after it has been passed to Java.

LuaJava is part of a larger project, called LuaOrb [CIR98, ICR98]. LuaOrb integrates a Lua script not only with Java components, but also with CORBAand COM components.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值