Adding member function to a C++ class bound to Lua

1.2k views Asked by At

I have been working on how to bind C++ classes to Lua for use in a game engine, and I have run into an interesting problem. I have been following the tutorial on this website: http://tinyurl.com/d8wdmea. After the tutorial, I realized that the following code he suggested:

local badguy = Monster.create();
badguy.pounce = function(self, howhigh, bonus)
    self.jumpbonus = bonus or 2;
    self:jump(howhigh);
    self:rawr();
end
badguy:pounce(5, 1);

Would only add the pounce function to that specific instance of a Monster. So I changed the script that he suggested to the following:

function Monster:pounce(howhigh, bonus)
    print("in pounce function");
    print(bonus);
    self.jumpbonus = bonus or 2
    self:jump(howhigh);
    self:rawr();
end
local badguy = Monster.create();
badguy:pounce(5,1);

However, when I call the pounce function, the script breaks. After further testing, the only way I was able to successfully call the pounce function was by calling the function as a static member of the Monster class (the code for the function stays the same):

Monster.pounce(badguy,5,1);

Syntactically, badguy:pounce(5,1) is correct, but isnt correctly calling the function. Am I just doing something wrong, or is this a limitation of the binding between lua and c++/how I am binding the two languages?

3

There are 3 answers

1
knowledge stacker On

it is not possible to call your C-Object/Function directly with all of its parameters. You have to register a C-Function into your Lua-State. This function has to look this way:

static int myfunc (lua_State *L) {
  // your code
  return X;  /* X = number of results */
}

This function receives only the Lua-State as parameter. All the parameters of the Luafunction call laying on the lua stack. You have to pop then from the Stack and Call your C++ method with it.

The registration of a function is quiet simple and done with two lines of code:

lua_pushcfunction(l, myfunc);
lua_setglobal(l, "myfuncnameinlua");

You can find more information about that in this chapter of the Book "programming in lua"

The thing you want to do, implementing an Lua-Object is a bit more complicated, because you have to register a metatable to create a Lua Object but your Lua to C interface are still functions of the explained kind.

You can also lean to implement a Lua-Object in Roberto Ierusalimschy's book on chapter 28

I hope this will help you

0
Nathan Wiebe On

I think I understand the question, and may have an idea of the solution. The is technically no link between the lua Monster 'class' and the C++ Monster class. When you call a lua 'member function' on a given lua object, it has no knowledge of the particular Monster object in C++. If you want to call a non-static method of a C++ object you cannot use a lua C-function to do this. You would need to have a user-data somewhere attached to your lua object that has a pointer to the C++ object (be very careful about object lifetimes - you must use full-userdata and override the __gc in lua with a C-function that destroys the C++ object). In this case, you can declare a private static C++ method on the Monster class that expects this userdata, and then casts the pointer and calls the non-static member function for this particular C++ monster object, with the given arguments. (I hope I understand your question, and that my answer is written clearly enough.)

0
mkluwe On

When you write

function Monster:pounce(howhigh, bonus)

this is a shortcut for

Monster.pounce = function(self, howhigh, bonus)

So obviously calling this by

Monster.pounce(badguy, 5, 1);

as you did makes sense.

But you want to do something different: From your C++ module you get a table named Monster. You don't want to manipulate this table itself, as it (only?) contains an entry named create, a monster's constructor.

I must admit that I don't completely get the code you linked to, but assuming a monster's method are accessed by a metatable, you could insert the method pounce in that metatable.