Subclass of {@link 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 {@link 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.
- {@link ZeroArgFunction}
- {@link OneArgFunction}
- {@link TwoArgFunction}
- {@link ThreeArgFunction}
- {@link VarArgFunction}
To be a Java library that can be loaded via {@code require}, it should have a public constructor that returns a {@link LuaValue} that, when executed, initializes the library.
For example, the following code will implement a library called "hyperbolic" with two functions, "sinh", and "cosh":
{@code import org.luaj.vm2.LuaValue;}public class hyperbolic extends org.luaj.vm2.lib.OneArgFunction public hyperbolic() {} public LuaValue call(LuaValue arg) { switch ( opcode ) { case 0: { LuaValue t = tableOf(); this.bind(t, hyperbolic.class, new String[] { "sinh", "cosh" }, 1 ); env.set("hyperbolic", t); return t; } case 1: return valueOf(Math.sinh(arg.todouble())); case 2: return valueOf(Math.cosh(arg.todouble())); default: return error("bad opcode: "+opcode); } } } }
The default constructor is both to instantiate the library in response to {@code require 'hyperbolic'} statement, provided it is on Javas class path, and to instantiate copies of the {@code hyperbolic} class when initializing library instances. . The instance returned by the default constructor will be invoked as part of library loading. In response, it creates two more instances, one for each library function, in the body of the {@code switch} statement {@code case 0} via the {@link #bind(LuaValue,Class,String[],int)} utility method.It also registers the table in the globals via the {@link #env} local variable, which should be the global environment unless it has been changed. {@code case 1} and {@code case 2} will be called when {@code hyperbolic.sinh}{@code hyperbolic.sinh} and {@code hyperbolic.cosh} are invoked.
To test it, a script such as this can be used:
{@code 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:
{@code t table: 3dbbd23f hyperbolic table: 3dbbd23f k,v cosh cosh k,v sinh sinh sinh(.5) 0.5210953 cosh(.5) 1.127626}
See the source code in any of the library functions such as {@link BaseLib} or {@link TableLib} for specific examples.