Class LibFunction

All Implemented Interfaces:
KryoSerializable
Direct Known Subclasses:
BaseLib.getmetatable, BaseLib.rawequal, BaseLib.rawget, BaseLib.rawlen, BaseLib.rawset, BaseLib.setmetatable, BaseLib.tonumber, BaseLib.tostring, BaseLib.type, CoroutineLib.create, CoroutineLib.status, CoroutineLib.wrap, DebugLib.getmetatable, DebugLib.getuservalue, MathLib.random, OneArgFunction, TableLib.concat, ThreeArgFunction, TwoArgFunction, VarArgFunction, ZeroArgFunction

public abstract class LibFunction extends LuaFunction implements KryoSerializable
Subclass of LuaFunction common to Java functions exposed to lua.

To provide for common implementations in JME and JSE, library functions are typically grouped on one or more library classes and an opcode per library function is defined and used to key the switch to the correct function within the library.

Since lua functions can be called with too few or too many arguments, and there are overloaded LuaValue.call() functions with varying number of arguments, a Java function exposed in lua needs to handle the argument fixup when a function is called with a number of arguments differs from that expected.

To simplify the creation of library functions, there are 5 direct subclasses to handle common cases based on number of argument values and number of return return values.

To be a Java library that can be loaded via require, it should have a public constructor that returns a LuaValue that, when executed, initializes the library.

For example, the following code will implement a library called "hyperbolic" with two functions, "sinh", and "cosh":

 
 import com.prineside.luaj.LuaValue;
 import com.prineside.luaj.lib.*;
 
 public class hyperbolic extends TwoArgFunction {

	public hyperbolic() {}

	public LuaValue call(LuaValue modname, LuaValue env) {
		LuaValue library = tableOf();
		library.set( "sinh", new sinh() );
		library.set( "cosh", new cosh() );
		env.set( "hyperbolic", library );
		return library;
	}

	static class sinh extends OneArgFunction {
		public LuaValue call(LuaValue x) {
			return LuaValue.valueOf(Math.sinh(x.checkdouble()));
		}
	}
	
	static class cosh extends OneArgFunction {
		public LuaValue call(LuaValue x) {
			return LuaValue.valueOf(Math.cosh(x.checkdouble()));
		}
	}
}
The default constructor is used to instantiate the library in response to require 'hyperbolic' statement, provided it is on Java"s class path. This instance is then invoked with 2 arguments: the name supplied to require(), and the environment for this function. The library may ignore these, or use them to leave side effects in the global environment, for example. In the previous example, two functions are created, 'sinh', and 'cosh', and placed into a global table called 'hyperbolic' using the supplied 'env' argument.

To test it, a script such as this can be used:

 
 local t = require('hyperbolic')
 print( 't', t )
 print( 'hyperbolic', hyperbolic )
 for k,v in pairs(t) do
 	print( 'k,v', k,v )
 end
 print( 'sinh(.5)', hyperbolic.sinh(.5) )
 print( 'cosh(.5)', hyperbolic.cosh(.5) )
 

It should produce something like:

 
 t	table: 3dbbd23f
 hyperbolic	table: 3dbbd23f
 k,v	cosh	function: 3dbbd128
 k,v	sinh	function: 3dbbd242
 sinh(.5)	0.5210953
 cosh(.5)	1.127626
 

See the source code in any of the library functions such as BaseLib or TableLib for other examples.