Sol Bind C++ Function To Lua
To register classes you use a class called class_. Its name is supposed toresemble the C++ keyword, to make it look more intuitive. It has an overloadedmember function def() that is used to register member functions, operators,constructors, enums and properties on the class. It will return itsthis-pointer, to let you register more members directly.
- Sol Bind C++ Function To Lua Command
- Using C++ Functions In Lua/Binding - Stack Overflow
- See More Results
- Efficiently Binding A LOT Of Things To Sol · Issue #436 ...
When you bind a function to Lua, please take any pointer arguments as T., unless you specifically know you are going to match the exact type of the unique/shared pointer and the class it wraps. Sol3 cannot support “implicit wrapped pointer casting”, such as taking a std::sharedptr when the function is passed a std::sharedptr. Sometimes it may work because the. The functions take a binding string, and arguments specifying the action to be performed. Notably, if you use this method to bind a key already bound to some action in the default Key Bindings UI, that binding will be unbound. The functions are: SetBinding for binding a generic command, or unbinding a key. SetBindingSpell; SetBindingItem.
Let’s start with a simple example. Consider the following C++ class:
To register it with a Lua environment, write as follows (assuming you are usingnamespace luabind):
This will register the class with the name testclass and constructor that takesa string as argument and one member function with the name print_string.
It is also possible to register free functions as member functions. Therequirement on the function is that it takes a pointer, const pointer,reference or const reference to the class type as the first parameter. The restof the parameters are the ones that are visible in Lua, while the objectpointer is given as the first parameter. If we have the following C++ code:
You can register plus() as if it was a member function of A like this:
plus() can now be called as a member function on A with one parameter, int.If the object pointer parameter is const, the function will act as if it was aconst member function (it can be called on const objects).
Overloaded member functions¶
When binding more than one overloads of a member function, or just bindingone overload of an overloaded member function, you have to disambiguatethe member function pointer you pass to def. To do this, you can use anordinary C-style cast, to cast it to the right overload. To do this, you haveto know how to express member function types in C++, here’s a short tutorial(for more info, refer to your favorite book on C++).
The syntax for member function pointer follows:
Here’s an example illlustrating this:

This selects the first overload of the function f to bind. The secondoverload is not bound.
Properties¶
To register a global data member with a class is easily done. Consider thefollowing class:
This class is registered like this:
This gives read and write access to the member variable A::a. It is alsopossible to register attributes with read-only access:
When binding members that are a non-primitive type, the auto generated getterfunction will return a reference to it. This is to allow chained .-operators.For example, when having a struct containing another struct. Like this:
When binding B to lua, the following expression code should work:
This requires the first lookup (on a) to return a reference to A, andnot a copy. In that case, luabind will automatically use the dependency policyto make the return value dependent on the object in which it is stored. So, ifthe returned reference lives longer than all references to the object (b inthis case) it will keep the object alive, to avoid being a dangling pointer.
You can also register getter and setter functions and make them look as if theywere a public data member. Consider the following class:
It can be registered as if it had a public data member a like this:
This way the get_a() and set_a() functions will be called instead ofjust writing to the data member. If you want to make it read only you can justomit the last parameter. Please note that the get function has to beconst, otherwise it won’t compile. This seems to be a common source of errors.
Enums¶
If your class contains enumerated constants (enums), you can register them aswell to make them available in Lua. Note that they will not be type safe, allenums are integers in Lua, and all functions that takes an enum, will acceptany integer. You register them like this:
In Lua they are accessed like any data member, except that they are read-onlyand reached on the class itself rather than on an instance of the class.
Operators¶

To bind operators you have to include <luabind/operator.hpp>.
The mechanism for registering operators on your class is pretty simple. You usea global name luabind::self to refer to the class itself and then you justwrite the operator expression inside the def() call. This class:
Is registered like this:
This will work regardless if your plus operator is defined inside your class oras a free function.
If your operator is const (or, when defined as a free function, takes a constreference to the class itself) you have to use const_self instead ofself. Like this:
The operators supported are those available in Lua:
This means, no in-place operators.
Default implementations (described below) are provided for and thespecial __tostring pseudo-operator. If any other operator is called, Luabindwill trigger an error (“[const] class <type>: no <metamethod name> defined.”,e.g. “class vec: no __div operator defined.”).
The equality operator () has a little hitch; it will not be called ifthe references are equal. This means that the operator has to do prettymuch what’s it’s expected to do.
For Luabind’s default operator, two objects are equal only if they areboth objects of Luabind-exported classes and have the same addresses, aftercasting both to a common base if neccessary. If they do not have a commonbase (and are not of the same type), they compare unequal.
Lua does not support operators such as !=, > or >=. That’s why youcan only register the operators listed above. When you invoke one of thementioned operators, lua will define it in terms of one of the availableoperators.
In the above example the other operand type is instantiated by writingint(). If the operand type is a complex type that cannot easily beinstantiated you can wrap the type in a class called other<>. For example:
To register this class, we don’t want to instantiate a string just to registerthe operator.
Instead we use the other<> wrapper like this:
To register an application (function call-) operator:
There’s one special operator. In Lua it’s called __tostring, it’s notreally an operator. It is used for converting objects to strings in a standardway in Lua. If you register this functionality, you will be able to use the luastandard function tostring() for converting your object to a string.
To implement this operator in C++ you should supply an operator<< forstd::ostream. Like this example:
If you do not define a __tostring operator, Luabind supplies a defaultwhich result in strings of the form [const]<type>object:<address>, i.e.const is prepended if the object is const, <type> will be the stringyou supplied to class_ (or a string derived from std::type_info::namefor unnamed classes) and <address> will be the address of the C++ object.(Note that in multiple inheritance scenarios where the same object is pushedas multiple different base types, the addresses returned for the samemost-derived object will differ).
Nested scopes and static functions¶
It is possible to add nested scopes to a class. This is useful when you needto wrap a nested class, or a static function.
In this example, f will behave like a static member function of the classfoo, and the class nested will behave like a nested class of foo.
It’s also possible to add namespaces to classes using the same syntax.
Derived classes¶
If you want to register classes that derives from other classes, you canspecify a template parameter bases<> to the class_ instantiation. Thefollowing hierarchy:
Would be registered like this:
If you have multiple inheritance you can specify more than one base. If B wouldalso derive from a class C, it would be registered like this:
Note that you can omit bases<> when using single inheritance.
Note
If you don’t specify that classes derive from each other, luabind will notbe able to implicitly cast pointers between the types.
Smart pointers¶
When registering a class you can tell luabind to hold all instancesexplicitly created in Lua in a specific smart pointer type, rather thanthe default raw pointer. This is done by passing an additional templateparameter to class_:
Where the requirements of P are:
Expression | Returns |
---|---|
P(raw) | |
get_pointer(p) | Convertible to X* |
where:
- raw is of type X*
- p is an instance of P
Sol Bind C++ Function To Lua Command
get_pointer() overloads are provided for the smart pointers inBoost, and std::auto_ptr<>. Should you need to provide your ownoverload, note that it is called unqualified and is expected to be foundby argument dependent lookup. Thus it should be defined in the samenamespace as the pointer type it operates on.
For example:
Will cause luabind to hold any instance created on the Lua side in aboost::scoped_ptr<X>. Note that this doesn’t mean all instanceswill be held by a boost::scoped_ptr<X>. If, for example, youregister a function:
the instance returned by that will be held in std::auto_ptr<X>. Thisis handled automatically for all smart pointers that implement aget_pointer() overload.
Important
get_const_holder() has been removed. Automatic conversionsbetween smart_ptr<X> and smart_ptr<Xconst> no longer work.
Important
__ok has been removed. Similar functionality can be implementedfor specific pointer types by doing something along the lines of:
When registering a hierarchy of classes, where all instances are to be heldby a smart pointer, all the classes should have the baseclass’ holder type.Like this:
Internally, luabind will do the necessary conversions on the raw pointers, whichare first extracted from the holder type.

This means that for Luabind a smart_ptr<derived> is not related to asmart_ptr<base>, but derived* and base* are, as aresmart_ptr<derived> and base*. In other words, upcasting does not workfor smart pointers as target types, but as source types.
Additional support for shared_ptr and intrusive_ptr¶
This limitation cannot be removed for all smart pointers in a generic way,but luabind has special support for
- boost::shared_ptr in shared_ptr_converter.hpp
- std::shared_ptr in std_shared_ptr_converter.hpp
- boost::intrusive_ptr in intrusive_ptr_converter.hpp
You should include the header(s) you need in the cpp files which registerfunctions that accept the corresponding smart pointer types, to get automaticconversions from smart_ptr<X> to smart_ptr<Y>, whenever Luabind wouldconvert X* to Y*, removing the limitation mentioned above.
Using C++ Functions In Lua/Binding - Stack Overflow
However, the shared_ptr converters might not behave exactly as you wouldexpect:
See More Results
If the shared_ptr requested (from C++) has the exact same type as theone which is present in Lua (if any), then a copy will be made.
If the pointee type of the requested shared_ptr has ashared_from_this member (checked automatically at compile time),this will be used to obtain a shared_ptr. Caveats:
If the object is not already held in a shared_ptr, behavior isundefined (probably a bad_weak_ptr exception will be thrown).
If the shared_from_this member is not a function with the rightprototype (ptr_tshared_from_this() with the expression
being valid, where raw is of type RequestedT* and points tothe C++ object in Lua.
Otherwise, a new shared_ptr will be created from the raw pointerassociated with the Lua object (even if it is not held in ashared_ptr). It will have a deleter set that holds a strongreference to the Lua object, thus preventing it’s collection until thereference is released by invoking the deleter (i.e. by resetting ordestroying the shared_ptr) or until the assocciated lua_Stateis closed: then the shared_ptr becomes dangling.
If such a shared_ptr is passed back to Lua, the original Lua object(userdata) will be passed instead, preventing the creation of moreshared_ptrs with this deleter.
1. is as you should have expected and 2. is special behavior introduced toavoid 3. when possible. If you cannot derive your (root) classes fromenable_shared_from_this (which is the recommended way of providing ashared_from_this method) you must be careful not to close thelua_State when you still have a shared_ptr obtained by 3.
There are three functions provided to support this (in namespace luabind):
is_state_unreferenced will return false if closing L would makeexisting shared_ptrs dangling and true if it safe (in this respect) tocall lua_close(L).
The cb argument passed to set_state_unreferenced_callback will becalled whenever the return value of is_state_unreferenced(L) would changefrom false to true.
get_state_unreferenced_callback returns the currentstate_unreferenced_fun for L.
A typical use of this functions would be to replace
with
Efficiently Binding A LOT Of Things To Sol · Issue #436 ...
(lua_close happens to be a valid state_unreferenced_fun.)
Unnamed classes¶
You can register unnamed classes by not passing a name to class_:
This does not export the class object itself to Lua, meaning thatconstructors cannot be called and enums are only accessible via objects ofthis class’ type.
This is useful e.g. for registering multiple instantiations of a classtemplate, and construct a matching instance using a factory function,like boost::make_shared of for hiding intermediate classes in inheritancehierarchies.
Splitting class registrations¶
In some situations it may be desirable to split a registration of a classacross different compilation units. Partly to save rebuild time when changingin one part of the binding, and in some cases compiler limits may force youto split it. To do this is very simple. Consider the following sample code:
Here, the class X is registered in two steps. The two functionsregister_part1 and register_part2 may be put in separate compilationunits.
To separate the module registration and the classes to be registered, seeSplitting up the registration.