Class: Lua::State

Inherits:
Object
  • Object
show all
Defined in:
rubyluabridge.cpp

Overview

The Ruby representation of a lua_State.

***************************************************************************

Instance Method Summary (collapse)

Constructor Details

- (Object) Lua::State.new(options)

Creates a new Lua::State.

options is a hash of options. If no options are specified, the default is { :loadlibs => :all }.

loadlibs: Invokes Lua::State.__loadlibs on the new Lua::State, passing the value of :loadlibs.

Raises NoMemoryError if the state cannot be allocated, or ArgumentError if the value of :loadlibs is invalid.



# File 'rubyluabridge.cpp'

/* call-seq: 
 *        Lua::State.new( options )
 * 
 * Creates a new Lua::State.
 * 
 * _options_ is a hash of options.  If no _options_ are specified, the default is { :loadlibs => :all }.
 * 
 * <b>loadlibs:</b>
 * Invokes Lua::State.__loadlibs on the new Lua::State, passing the value of :loadlibs.
 * 
 * Raises NoMemoryError if the state cannot be allocated, or ArgumentError if the value of :loadlibs
 * is invalid.
 */
static VALUE rlua_State_initialize( int argc, VALUE* argv, VALUE self )
{
    rlua_State* pRLState;
    Data_Get_Struct( self, rlua_State, pRLState ); 

    // create new Lua state
    pRLState->Lstate.reset( luaL_newstate(), lua_close_deleter() );
    if ( !pRLState->getState() )
        rb_raise( rb_eNoMemError, "lua_State memory allocation failed" );

    RLB_DEBUG_PRINT( "state   init: ptr:%p   L:%p\n", pRLState, pRLState->getState() );

    // if there is no arguments (or nil first value), load all
    if ( argc == 0 || NIL_P(argv[0]) ) {
        luaL_openlibs( pRLState->getState() );
        return self;
    }
    // otherwise, it has to be a hash
    Check_Type( argv[0], T_HASH );
    
    // process "loadlibs"
    VALUE libs = rb_hash_aref( argv[0], ID2SYM(rb_intern("loadlibs")) );
    rlua_State_loadlibs( self, libs ); // OK if nil
        
    return self;
}

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

- (Object) Lua::State.method_missing

This method is called by Ruby when it sees an Object can’t handle a message. We use it to dispatch to Lua, attempting a lookup of that value in the Lua::State’s global table.

If the method name has an ‘=’ at the end, it is treated as an assignment, in which case it assigns the first value. It returns that value for chaining.

The first argument is the symbol of the message name, the rest are its args.



# File 'rubyluabridge.cpp'

/* call-seq: 
 *        Lua::State.method_missing -> result
 * 
 * This method is called by Ruby when it sees an Object can't handle a message.
 * We use it to dispatch to Lua, attempting a lookup of that value in the Lua::State's global table.
 * 
 * If the method name has an '<tt>=</tt>' at the end, it is treated as an assignment,
 * in which case it assigns the first value.  It returns that value for chaining.
 * 
 * The first argument is the symbol of the message name, the rest are its args.
 */
VALUE rlua_State_method_missing( int argc, VALUE* argv, VALUE self )
{
    rlua_State* pRLstate;
    Data_Get_Struct( self, rlua_State, pRLstate ); 
    lua_State* L = pRLstate->getState();

    Check_Type( argv[0], T_SYMBOL );
    ID methodid = SYM2ID( argv[0] );
    const char* key = rb_id2name( methodid );
    
    lua_pushvalue( L, LUA_GLOBALSINDEX );
    return rlua_method_missing_dispatch( L, key, self, argc, argv );
}

Instance Method Details

- (Object) Lua::State

Returns the value indexed at key in the Lua::State’s globals table.



# File 'rubyluabridge.cpp'

/* call-seq: 
 *        Lua::State[key] -> value
 *
 * Returns the value indexed at _key_ in the Lua::State's globals table.  
 */
VALUE rlua_State_getindex( VALUE self, VALUE key )
{
    rlua_State* pRLstate;
    Data_Get_Struct( self, rlua_State, pRLstate ); 
    lua_State* L = pRLstate->getState();
    
    marshal_ruby_to_lua_top( L, key );
    lua_gettable( L, LUA_GLOBALSINDEX );

    // marshal the result to Ruby
    VALUE result = marshal_lua_to_ruby( self, L, -1 );
    lua_pop( L, 1 );
    return result;
}

- (Object) Lua::State

Assigns value to be indexed at key in the Lua::State’s globals table. Returns the value for chaining.



# File 'rubyluabridge.cpp'

/* call-seq: 
 *        Lua::State[key] = value -> value
 *
 * Assigns _value_ to be indexed at _key_ in the Lua::State's globals table.  
 * Returns the value for chaining.
 */
VALUE rlua_State_setindex( VALUE self, VALUE key, VALUE val )
{
    rlua_State* pRLstate;
    Data_Get_Struct( self, rlua_State, pRLstate ); 
    lua_State* L = pRLstate->getState();
    
    marshal_ruby_to_lua_top( L, key );
    marshal_ruby_to_lua_top( L, val );
    lua_settable( L, LUA_GLOBALSINDEX );

    return val;    // return val for chaining
}

- (Object) Lua::State.__globals

Returns the globals table of this Lua::State. It is an instance of the Lua::Table class.



# File 'rubyluabridge.cpp'

/* call-seq: 
 *        Lua::State.__globals -> Lua::Table
 * 
 * Returns the globals table of this Lua::State.
 * It is an instance of the Lua::Table class.
 */
static VALUE rlua_State_globals( VALUE self )
{ 
    rlua_State* pRLState;
    Data_Get_Struct( self, rlua_State, pRLState ); 
    lua_State* L = pRLState->getState();
    
    lua_pushvalue( L, LUA_GLOBALSINDEX );
    VALUE result = marshal_lua_to_ruby( self, L, -1 );
    lua_pop( L, 1 );
    return result;    
}

- (Object) Lua::State.__loadlib(libs)

Loads the specified Lua standard libraries into the Lua::State.

If libs is not specified, all libraries are loaded. Otherwise, if libs is a symbol, that library is loaded. Special symbols are :all, which loads all libraries, and :none which loads no libraries. If libs is an Array, all symbols in the Array are loaded (in the order specified); in this case, :all and :none are ignored; an empty Array will load no libraries. If none of the above fits, an ArgumentError is raised.

Supported libraries are:

  • base

  • package

  • table

  • io

  • os

  • string

  • math

  • debug



# File 'rubyluabridge.cpp'

/* call-seq: 
 *      Lua::State.__loadlib( libs )
 * 
 * Loads the specified Lua standard libraries into the Lua::State.
 * 
 * If _libs_ is not specified, all libraries are loaded.  Otherwise, if _libs_ is a symbol, that library
 * is loaded.  Special symbols are :all, which loads all libraries, and :none which loads no libraries.
 * If _libs_ is an Array, all symbols in the Array are loaded (in the order specified); in this case,
 * :all and :none are ignored; an empty Array will load no libraries.  If none of the above fits,
 * an ArgumentError is raised.
 * 
 * Supported libraries are: 
 * - base
 * - package
 * - table
 * - io
 * - os
 * - string
 * - math
 * - debug
 */
static VALUE rlua_State_loadlibs( VALUE self, VALUE libs )
{
    rlua_State* pRLState;
    Data_Get_Struct( self, rlua_State, pRLState ); 
    lua_State* L = pRLState->getState();
    
    // if it is empty or :all, load all
    // if it is a symbol, load that the lib it matches
    // if it is :none, load none
    // if it is an array, load all its symbols (:all is ignored here)
    // otherwise, load none
    if ( NIL_P(libs) )
    {
        luaL_openlibs( L );
    } 
    else if ( TYPE(libs) == T_SYMBOL )
    {
        const char* libname = rb_id2name( SYM2ID(libs) );
        if ( !strcmp(libname, "all") )
            luaL_openlibs( L );
        else if ( !strcmp(libname, "none") )
        {}  // load none on :none
        else
            load_std_library_by_name( L, libname );
    }
    else if ( TYPE(libs) == T_ARRAY )
    {
        int i;
        for ( i = 0; i < RARRAY(libs)->len; i++ )
        {
            VALUE entry = RARRAY(libs)->ptr[i];
            if ( TYPE(entry) == T_SYMBOL )
            {
                const char* libname = rb_id2name( SYM2ID(entry) );
                load_std_library_by_name( L, libname );
            }
        }
    }
    else
        rb_raise( rb_eArgError, "loadlibs must be Nil, a Symbol, or an Array of symbols" );
        
    return self;
}

- (Object) Lua::State.__registry

Returns the registry table of this Lua::State. It is an instance of the Lua::Table class.

As the Lua Registry is intended for C extensions and the Lua reference system, be careful modifying values stored in this table.



# File 'rubyluabridge.cpp'

/* call-seq: 
 *        Lua::State.__registry -> Lua::Table
 * 
 * Returns the registry table of this Lua::State.
 * It is an instance of the Lua::Table class.
 * 
 * As the Lua Registry is intended for C extensions
 * and the Lua reference system, be careful modifying
 * values stored in this table.
 */
static VALUE rlua_State_registry( VALUE self )
{ 
    rlua_State* pRLState;
    Data_Get_Struct( self, rlua_State, pRLState ); 
    lua_State* L = pRLState->getState();

    lua_pushvalue( L, LUA_REGISTRYINDEX );
    VALUE result = marshal_lua_to_ruby( self, L, -1 );
    lua_pop( L, 1 );
    return result;    
}

- (Object) Lua::State.__state

Returns this Lua::State itself.

Introduced for parallelism with Lua::RefObject.__state.



# File 'rubyluabridge.cpp'

/* call-seq: 
 *        Lua::State.__state -> Lua::State
 * 
 * Returns this Lua::State itself.
 * 
 * Introduced for parallelism with Lua::RefObject.__state.
 */
static VALUE rlua_State_state( VALUE self )
{
    return self;
}

- (Integer) Lua::State.__top

Return the absolute position of the top of the lua_State’s stack.

This is mainly for debugging/testing purposes.

Returns:

  • (Integer)


# File 'rubyluabridge.cpp'

/* call-seq: 
 *        Lua::State.__top -> int
 * 
 * Return the absolute position of the top of the lua_State's stack.
 *
 * This is mainly for debugging/testing purposes.
 */
static VALUE rlua_State_top( VALUE self )
{ 
    rlua_State* pRLState;
    Data_Get_Struct( self, rlua_State, pRLState ); 
    int top = lua_gettop( pRLState->getState() );
    return INT2NUM( top ); 
}

- (true) Lua::State.callable?

Returns whether Lua:State is callable (like via __cal), which it is not.. This is to provide consistency with Lua::RefObject interface.

Returns:

  • (true)


# File 'rubyluabridge.cpp'

/* call-seq: 
 *        Lua::State.callable? -> true
 * 
 * Returns whether Lua:State is callable (like via __cal), which it is not..
 * This is to provide consistency with Lua::RefObject interface.
 */
VALUE rlua_State_is_callable( VALUE self )
{
    return Qfalse;
}

- (Object) Lua::State.eval

Evaluates the passed string in the Lua::State.

Returns the first value returned by the evaluation.



# File 'rubyluabridge.cpp'

/* call-seq: 
 *        Lua::State.eval -> result
 * 
 * Evaluates the passed string in the Lua::State.
 * 
 * Returns the first value returned by the evaluation.
 */
static VALUE rlua_State_eval( VALUE self, VALUE str )
{
    // verify and marshal Ruby args to C
    rlua_State* pRLState;
    Data_Get_Struct( self, rlua_State, pRLState ); 
    SafeStringValue(str); 
    lua_State* L = pRLState->getState();
    
    // process the string to a chunk
    int err = luaL_loadbuffer( L, RSTRING(str)->ptr, RSTRING(str)->len, "Lua::State.eval" );
    if ( err == LUA_ERRMEM )
        rb_raise( rb_eNoMemError, pop_error_to_buffer(L) );
    else if ( err == LUA_ERRSYNTAX )
        rb_raise( rb_eSyntaxError, pop_error_to_buffer(L) );

    // pcall the chunk, returning only a single argument
    // TODO: error handler with stack traceback
    // TODO: it would be nice to have it configurable whether to print the traceback
    // TODO: hmmm... the err handler could even be in Ruby?
    err = lua_pcall( L, 0, 1, 0 );
    if ( err == LUA_ERRRUN )
        rb_raise( rb_eRuntimeError, pop_error_to_buffer(L) );
    else if ( err == LUA_ERRMEM )
        rb_raise( rb_eNoMemError, pop_error_to_buffer(L) );
    else if ( err == LUA_ERRERR )
        rb_raise( rb_eFatal, pop_error_to_buffer(L) );

    // marshal the result to Ruby
    VALUE result = marshal_lua_to_ruby( self, L, -1 );
    lua_pop( L, 1 );
    return result;
}

- (Object) Lua::State.eval_mult

Evaluates the passed string in the Lua::State.

Returns the all the return values in a Ruby array (with the first result first). If there are no results, an empty array is returned.



# File 'rubyluabridge.cpp'

/* call-seq: 
 *        Lua::State.eval_mult -> Array
 * 
 * Evaluates the passed string in the Lua::State.
 * 
 * Returns the all the return values in a Ruby array (with the first result first).
 * If there are no results, an empty array is returned.
 */
static VALUE rlua_State_eval_mult( VALUE self, VALUE str )
{
    // verify and marshal Ruby args to C
    rlua_State* pRLState;
    Data_Get_Struct( self, rlua_State, pRLState ); 
    SafeStringValue(str); 
    lua_State* L = pRLState->getState();
    int args_bottom = lua_gettop(L);

    // process the string to a chunk
    int err = luaL_loadbuffer( L, RSTRING(str)->ptr, RSTRING(str)->len, "Lua::State.eval" );
    if ( err == LUA_ERRMEM )
        rb_raise( rb_eNoMemError, pop_error_to_buffer(L) );
    else if ( err == LUA_ERRSYNTAX )
        rb_raise( rb_eSyntaxError, pop_error_to_buffer(L) );

    // pcall the chunk, returning only a single argument
    // TODO: error handler with stack traceback
    // TODO: it would be nice to have it configurable whether to print the traceback
    // TODO: hmmm... the err handler could even be in Ruby?
    err = lua_pcall( L, 0, LUA_MULTRET, 0 );
    if ( err == LUA_ERRRUN )
        rb_raise( rb_eRuntimeError, pop_error_to_buffer(L) );
    else if ( err == LUA_ERRMEM )
        rb_raise( rb_eNoMemError, pop_error_to_buffer(L) );
    else if ( err == LUA_ERRERR )
        rb_raise( rb_eFatal, pop_error_to_buffer(L) );

    // marshal the result to Ruby
    int args_top = lua_gettop(L);
    int nres = args_top - args_bottom;
    int li, ri;
    VALUE ary_res = rb_ary_new2( nres );
    for ( li = args_bottom+1, ri = 0; li <= args_top; ++li, ++ri )
        rb_ary_store( ary_res, ri, marshal_lua_to_ruby(self, L, li) );
    lua_pop( L, nres );
    return ary_res;
}

- (true) Lua::State.indexable?

Returns whether Lua:State is indexable (via __index), which it is. This is to provide consistency with Lua::RefObject interface.

Returns:

  • (true)


# File 'rubyluabridge.cpp'

/* call-seq: 
 *        Lua::State.indexable? -> true
 * 
 * Returns whether Lua:State is indexable (via __index), which it is.
 * This is to provide consistency with Lua::RefObject interface.
 */
VALUE rlua_State_is_indexable( VALUE self )
{
    return Qtrue;
}

- (true) Lua::State.new_indexable?

Returns whether Lua:State can create new indices (via __newindex), which it can. This is to provide consistency with Lua::RefObject interface.

Returns:

  • (true)


# File 'rubyluabridge.cpp'

/* call-seq: 
 *        Lua::State.new_indexable? -> true
 * 
 * Returns whether Lua:State can create new indices (via __newindex), which it can.
 * This is to provide consistency with Lua::RefObject interface.
 */
VALUE rlua_State_is_new_indexable( VALUE self )
{
    return Qtrue;
}

- (Object) Lua::State.new_table_at(key)

Creates a new table at the given key. Returns the new table.



# File 'rubyluabridge.cpp'

/* call-seq: 
 *        Lua::State.new_table_at key -> Lua::Table
 * 
 * Creates a new table at the given key.  Returns the new table.
 */
VALUE rlua_State_new_table_at( VALUE self, VALUE key )
{
    rlua_State* pRLstate;
    Data_Get_Struct( self, rlua_State, pRLstate ); 
    lua_State* L = pRLstate->getState();

    marshal_ruby_to_lua_top( L, key );
    lua_newtable( L );
    
    VALUE result = marshal_lua_to_ruby( self, L, -1 );
    lua_settable( L, LUA_GLOBALSINDEX );
    
    return result;
}