Class: Lua::Function

Inherits:
Object
  • Object
show all
Defined in:
ext/rlua.c

Instance Method Summary collapse

Constructor Details

#Lua::Function.new(state, proc) ⇒ Object

Converts a Ruby closure proc to a Lua function in Lua::State represented by state. Note that you generally do not need to call this function explicitly: any proc or lambda passed as a value for table assignment will be automagically converted to Lua closure.



531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
# File 'ext/rlua.c', line 531

static VALUE rbLuaFunction_initialize(int argc, VALUE* argv, VALUE self)
{
  VALUE rbLuaState, ref = Qnil, func;
  rb_scan_args(argc, argv, "11", &rbLuaState, &func);
  
  if(rb_obj_class(rbLuaState) != cLuaState)
    rb_raise(rb_eTypeError, "wrong argument type %s (expected Lua::State)", rb_obj_classname(rbLuaState));
  
  VALUE rbState = rb_iv_get(rbLuaState, "@state");
  rb_iv_set(self, "@state", rbState);
  
  lua_State* state;
  Data_Get_Struct(rbState, lua_State, state);
  
  VALUE proc = Qnil;
  
  if(TYPE(func) == T_FIXNUM)
    ref = func;
  else if(rb_respond_to(func, rb_intern("call")))
    proc = func;
  else
    rb_raise(rb_eTypeError, "wrong argument type %s (expected Proc)", rb_obj_classname(func));

  if(ref == Qnil) {
    lua_pushlightuserdata(state, (void*) proc);
    lua_pushcclosure(state, call_ruby_proc, 1);
    ref = rlua_makeref(state);
    lua_pop(state, 1);
    
    // don't allow GC to collect proc
    rb_iv_set(self, "@proc", proc);
  }
  
  rlua_add_ref_finalizer(rbState, ref, self);

  rb_iv_set(self, "@ref", ref);
  
  return self;
}

Instance Method Details

#==(other) ⇒ Boolean

Compares this with other. May call __eq metamethod.

Returns:

  • (Boolean)


823
824
825
826
827
828
829
830
831
832
833
834
835
# File 'ext/rlua.c', line 823

static VALUE rbLua_equal(VALUE self, VALUE other)
{
  lua_State* state;
  Data_Get_Struct(rb_iv_get(self, "@state"), lua_State, state);

  int equal;
  rlua_push_var(state, self);           // stack: |this|...
  rlua_push_var(state, other);          //        |othr|this|...
  equal = lua_equal(state, -1, -2);     //        |othr|this|...
  lua_pop(state, 2);                    //        ...

  return equal ? Qtrue : Qfalse;
}

#__envLua::Table

Returns environment table of Lua::State or Lua::Function.

Returns:



688
689
690
691
692
693
694
695
696
697
698
699
700
# File 'ext/rlua.c', line 688

static VALUE rbLua_get_env(VALUE self)
{
  lua_State* state;
  Data_Get_Struct(rb_iv_get(self, "@state"), lua_State, state);
  
  VALUE ref;
  rlua_push_var(state, self);                   // stack: |this|...
  lua_getfenv(state, -1);                       //        |envi|this|...
  ref = rlua_makeref(state);                    //        |envi|this|...
  lua_pop(state, 2);                            //        ...

  return rb_funcall(cLuaTable, rb_intern("new"), 2, self, ref);
}

#__env=(table) ⇒ Object

Sets environment table for Lua::State or Lua::Function. table may be a Lua::Table or a Hash.



708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
# File 'ext/rlua.c', line 708

static VALUE rbLua_set_env(VALUE self, VALUE env)
{
  lua_State* state;
  Data_Get_Struct(rb_iv_get(self, "@state"), lua_State, state);
  
  if(rb_obj_class(env) != cLuaTable && TYPE(env) != T_HASH)
    rb_raise(rb_eTypeError, "wrong argument type %s (expected Lua::Table or Hash)", rb_obj_classname(env));

  rlua_push_var(state, self);                      // stack: |this|...
  rlua_push_var(state, env);                       //        |envi|this|...
  lua_setfenv(state, -2);                          //        |this|...
  lua_pop(state, 1);                               //        ...
  
  return env;
}

#__equal(other) ⇒ Boolean

Compares this with other without calling any metamethods.

Returns:

  • (Boolean)


842
843
844
845
846
847
848
849
850
851
852
853
854
# File 'ext/rlua.c', line 842

static VALUE rbLua_rawequal(VALUE self, VALUE other)
{
  lua_State* state;
  Data_Get_Struct(rb_iv_get(self, "@state"), lua_State, state);

  int equal;
  rlua_push_var(state, self);           // stack: |this|...
  rlua_push_var(state, other);          //        |othr|this|...
  equal = lua_rawequal(state, -1, -2);  //        |othr|this|...
  lua_pop(state, 2);                    //        ...

  return equal ? Qtrue : Qfalse;
}

#call(*args) ⇒ Object

Invokes a Lua function in protected environment (like a Lua xpcall).

One value returned in Lua is returned as one value in Ruby; multiple values returned in Lua are returned as an array of them in Ruby. This convention allows usage of identical code for calling methods with multiple return values in both languages.

While you can easily call Lua procedures and use their return values, returning multiple values from Ruby is not that easy. RLua cannot guess whether array returned by Ruby function is a ‘real’ array or just several return values, so there is a Lua.multret proxy method for that purpose. Ruby return values constructed with multret method are automatically unpacked to multiple return values. Example:

state = Lua::State.new
state.p = lambda{ |*args| p *args }
state.f1 = Lua::Function.new(state, lambda{ [ 1, 2, 3 ] })
state.f2 = Lua::Function.new(state, lambda{ Lua.multret( 1, 2, 3 ) })
state.__eval("p(f1())") # results in { 1.0, 2.0, 3.0 } Lua table
                        # shown as array
state.__eval("p(f2())") # results in 1.0, 2.0, 3.0 Lua multiple return values
                        # shown as three separate values

Any Lua error that has appeared during the call will be raised as Ruby exception with message equal to Lua error message. *Lua error messages are explicitly converted to strings with lua_tostring function.* Lua errors are mapped as follows:

LUA_ERRMEM

NoMemError is raised.

LUA_ERRRUN

RuntimeError is raised.

Note that if any uncatched exception is raised in Ruby code inside Lua::Function it will be propagated as Lua error. *In this case the backtrace is lost!* Catch your exceptions in Ruby code if you want to keep their backtraces.

This ‘drawback’ is intentional: while it is technically possible to re-raise the same Exception object, the backtrace will lead to re-raise point anyway.



614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
# File 'ext/rlua.c', line 614

static VALUE rbLuaFunction_call(VALUE self, VALUE args)
{
  lua_State* state;
  Data_Get_Struct(rb_iv_get(self, "@state"), lua_State, state);

  int i;
  VALUE retval;

  rlua_push_var(state, self);                      // stack: |this|...
  for(i = 0; i < RARRAY_LEN(args); i++)
    rlua_push_var(state, RARRAY_PTR(args)[i]);
                                                   //        |argN-arg1|this|...
  retval = rlua_pcall(state, RARRAY_LEN(args));    //        ...

  return retval;
}