# class Lua::State

The Ruby representation of a lua_State.

### Public Class Methods

Lua::State.new( options ) click to toggle source

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.

    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;
    }

### Public Instance Methods

Lua::State[key] → value click to toggle source

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;
    }

Lua::State[key] = value → value click to toggle source

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
    }

Lua::State.__globals → Lua::Table click to toggle source

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;
    }

Lua::State.__loadlib( libs ) click to toggle source

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_LEN(libs); i++ )
            {
                VALUE entry = RARRAY_PTR(libs)[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;
    }

Lua::State.__registry → Lua::Table click to toggle source

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;
    }

Lua::State.__state → Lua::State click to toggle source

Returns this `Lua::State` itself.

Introduced for parallelism with `Lua::RefObject`.__state.

    static VALUE rlua_State_state( VALUE self )
    {
        return self;
    }

Lua::State.__top → int click to toggle source

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 );
    }

Lua::State.callable? → true click to toggle source

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;
    }

Lua::State.eval → result click to toggle source

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_PTR(str), RSTRING_LEN(str), "Lua::State.eval" );
        if ( err == LUA_ERRMEM )
            rb_raise( rb_eNoMemError, "%s", pop_error_to_buffer(L) );
        else if ( err == LUA_ERRSYNTAX )
            rb_raise( rb_eSyntaxError, "%s", 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, "%s", pop_error_to_buffer(L) );
        else if ( err == LUA_ERRMEM )
            rb_raise( rb_eNoMemError, "%s", pop_error_to_buffer(L) );
        else if ( err == LUA_ERRERR )
            rb_raise( rb_eFatal, "%s", 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;
    }

Lua::State.eval_mult → Array click to toggle source

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_PTR(str), RSTRING_LEN(str), "Lua::State.eval" );
        if ( err == LUA_ERRMEM )
            rb_raise( rb_eNoMemError, "%s", pop_error_to_buffer(L) );
        else if ( err == LUA_ERRSYNTAX )
            rb_raise( rb_eSyntaxError, "%s", 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, "%s", pop_error_to_buffer(L) );
        else if ( err == LUA_ERRMEM )
            rb_raise( rb_eNoMemError, "%s", pop_error_to_buffer(L) );
        else if ( err == LUA_ERRERR )
            rb_raise( rb_eFatal, "%s", 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;
    }

Lua::State.indexable? → true click to toggle source

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;
    }

Lua::State.method_missing → result click to toggle source

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.

    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 );
    }

Lua::State.new_indexable? → true click to toggle source

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;
    }

Lua::State.new_table_at key → Lua::Table click to toggle source

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;
    }