3

I'm using Lua interface on c# to pass an object I created to lua's function. It successfully calls the function, but lua is keep throwing an error:

LuaInterface.LuaException: /hook.lua:32: attempt to index local 'objj' (a nil value)

This is the c# code:

public class PerObj
{
    public string name;
    public PerObj() 
    {
    }
}

PerObj obj = new PerObj();
LuaFunction lf = lua.GetFunction ("item.HookMe");
lf.Call(obj);

And here's the lua code:

function item:HookMe(objj)
    objj.name= "lalala"
end

The function is actually being called, but I'm not sure it's not working...

hjpotter92
  • 78,589
  • 36
  • 144
  • 183
Max Hunter
  • 33
  • 6

2 Answers2

0

Change the function definition to:

function item.HookMe(objj)
    objj.name= "lalala"
end

The colon in the original definition means that the function has also the self parameter. Those function are called like this: object:HookMe(). But you want to call it directly, so the colon is not applicable.

Edit:
If you want to keep the function defininition and retain self, call it like this:

lf.Call(null, obj);

To call it passing also the self object:

lf.Call(lua["item"], obj);
IS4
  • 11,945
  • 2
  • 47
  • 86
  • Thanks! If this has a self parameter, if I call the function (object:HookMe()) with :"lf.Call(null, obj);", what would happen? Would it be simply ignored? How would I retain "self" when I call the function? – Max Hunter Mar 09 '15 at 15:51
  • @Max Yes, you can simply pass null as the first argument to `self`. – IS4 Mar 09 '15 at 17:07
  • This makes "self" (also used in the function) nil. What are some other ways to retain self? – Max Hunter Mar 09 '15 at 17:11
  • @Max It depends on what you expect `self` to be. If `item` is an object, you can call it like this: `Call(lua["item"], objj)` – IS4 Mar 09 '15 at 17:14
  • Hm, then there's no way to let Lua interface ignore the first argument so "self" works when it's called through object:HookMe ()? – Max Hunter Mar 09 '15 at 17:47
  • @Max I don't understand. In Lua, you implicitly specify the `self` argument in the "colon call". If you do `object:HookMe()`, it's exactly the same as `object.HookMe(object)`. You just have to specify the object you want to call the function on. – IS4 Mar 09 '15 at 19:15
  • Oh yes, I got what you meant. Sorry if my question wasn't clear. If you were calling woop:HookMe(obj) through C#, I want to call the function using .Call(>, obj). if I put null for >, "self" in Lua would return "nil" instead of "woop". I want "self" to return itself in Lua while being able to use "Call ()" from C#. – Max Hunter Mar 09 '15 at 22:29
  • @Max Lua function don't have "self" attached to them, if you write `func = woop:HookMe` and then `func(obj)`, the `obj` will be passed as `self` and the original `woop` will be lost. `self` is just a syntactic sugar for the first parameter, not something special. – IS4 Mar 10 '15 at 01:11
  • I see. That's really weird. Thanks! – Max Hunter Mar 10 '15 at 02:04
0

It seems like the problem is the design of the Lua method (but it really depends on the intent):

Instead of

function item:HookMe(objj)
    -- self not used
    objj.name= "lalala"
end

This would work better in the given example:

function item:HookMe()
    self.name= "lalala"
end

The reason (as well discussed in other answers) is that declaring a function with the method syntax (:) adds an implied first formal parameter self. The caller can pass anything as the first actual argument but the contract is usually to pass the parent table of the function so it can access its sibling fields.

In this case, name seems to be a sibling of HookMe so the method shouldn't be operating on an arbitrary table passed as objj but instead on self.

Tom Blodget
  • 20,260
  • 3
  • 39
  • 72