Implementing Virtual Methods With Toluapp

lua-users home
wiki

This tolua++ addon can be used to generate code to allow c++ virtual methods to be implemented from lua. This code is a modified version of the code used on lua_qt, combined with ToluappClassAccessLabels to implement access labels. Note that this is not a patch; it can be used with an unmodified tolua++ binary (version 1.0.7 or higher).

2 files are needed:

Files:wiki_insecure/users/ArielManzur/tolua++/virtual_method_hooks.lua

Files:wiki_insecure/users/ArielManzur/tolua++/tolua_base.h

Usage example

Create a .pkg file

// mypackage.pkg

$#include "tolua_base.h"

class Widget {

protected:
   virtual bool input_event(Event* e);

public:

   virtual void add_child(Widget* child);

   void close();

   Widget(string p_name);
};

Generate the package

tolua++ -L virtual_method_hooks.lua mypackage.pkg > mypackage.cpp
(compile 'mypackage.cpp' with the rest of the code)

Use the class Lua__Widget from your lua script


-- custom_widget.lua
require "mypackage"

local CustomWidget = {}
CustomWidget.__index = CustomWidget

function CustomWidget:input_event(e)

   if e.type = Event.KEY_PRESS and e.key_code == KEY_ESCAPE then
      -- close the widget when escape is pressed
      self:close()
      return true
   end

   -- call Widget::input_event
   return self:Widget__input_event(e)
end

function CustomWidget:new(name)

   -- create a table and make it an 'instance' of CustomWidget
   local t = {}
   setmetatable(t, CustomWidget)

   -- create a Lua__Widget object, and make the table inherit from it
   local w = Lua__Widget:new(name)
   tolua.setpeer(w, t) -- use 'tolua.inherit' on lua 5.0

   -- 'w' will be the lua object where the virtual methods will be looked up
   w:tolua__set_instance(w)

   return w -- return 't' on lua 5.0 with tolua.inherit
end

In this example, the class 'Lua__Widget' is generated. Lua__Widget has all the constructors of Widget, and a method 'tolua__set_instance', to provide the lua object where the virtual methods will be looked up (in this case, we use the same userdata object used for the c++ object, because our lua functions override the c++ functions). This object will be passed as self on the lua methods. Lua__Widget also exposes the virtual methods from Widget to be called directly.

Inheritance

A subclass that inherits from a class with virtual methods will also generate code to implement those methods from lua, but only if the subclass has any virtual methods itself. For example, if we add the following to our pkg:

class Label : public Widget {

public:
   void set_text(string p_text);
};

this will not generate a Lua__Label class. For that, we need to add at least one virtual method. Consider the following example:

class Label : public Widget {

private:
   virtual void add_child(Widget* child);

public:
   void set_text(string p_text);
};

In this case, the only virtual method available for the class Lua__Label will be input_event (inherited from Widget). The reason to declare add_child as private on the pkg is because if the method is actually private and we don't declare it as such on the pkg, the generated code will try to use it on Lua__Label, and that will produce a compile error.

Tweaking

The file virtual_method_hooks.lua has 3 flags that can be changed (found at the beginning of the file).

Overloading

Since lua doesn't enforce signatures for functions, the only way to lookup a function is by its name, so when there are more than 1 c++ methods with the same name, your lua function should be prepared to handle all versions of the functions.

Also, when looking for methods on parent classes, only the names are used to match them (this is a limitation of the current version). For example, if you add this to the example package:


class Button : public Widget {

public:
   virtual void add_child(Label* child);
};

only the last version of add_child will be available for the class Lua__Button.

Other limitations

Only one level of namespaces is supported for the moment. To avoid infinite recursion, only lua functions (and not lua_cfunctions) are called from the virtual methods.

Some versions of tolua++ (like 1.0.92) have problems with the 'default_private_access' flag. If the methods on your virtual class are not being exported, try setting the flag to false. You'll have to add a private: label to the class declarations that have private stuff by default at the beginning.

Contact

Send questions, bugs, or comments to mailto:puntob@gmail.com


RecentChanges · preferences
edit · history
Last edited January 20, 2009 6:38 pm GMT (diff)