Binding functions to Lua

To bind functions to Lua you use the function luabind::def(). It has the following synopsis:

template<class F, class policies>
void def(const char* name, F f, const Policies&);
  • name is the name the function will have within Lua.
  • F is the function pointer you want to register.
  • The Policies parameter is used to describe how parameters and return values are treated by the function, this is an optional parameter. More on this in the Policies section.

An example usage could be if you want to register the function float std::sin(float):

module(L)
[
    def("sin", &std::sin)
];

Overloaded functions

If you have more than one function with the same name, and want to register them in Lua, you have to explicitly give the signature. This is to let C++ know which function you refer to. For example, if you have two functions, int f(const char*) and void f(int).

module(L)
[
    def("f", (int(*)(const char*)) &f),
    def("f", (void(*)(int)) &f)
];

Signature matching

luabind will generate code that checks the Lua stack to see if the values there can match your functions’ signatures. It will handle implicit typecasts between derived classes, and it will prefer matches with the least number of implicit casts. In a function call, if the function is overloaded and there’s no overload that match the parameters better than the other, you have an ambiguity. This will spawn a run-time error, stating that the function call is ambiguous. A simple example of this is to register one function that takes an int and one that takes a float. Since Lua doesn’t distinguish between floats and integers, both will always match.

Since all overloads are tested, it will always find the best match (not the first match). This also means that it can handle situations where the only difference in the signature is that one member function is const and the other isn’t.

For example, if the following function and class is registered:

struct A
{
    void f();
    void f() const;
};

const A* create_a();

struct B: A {};
struct C: B {};

void g(A*);
void g(B*);

And the following Lua code is executed:

a1 = create_a()
a1:f() -- the const version is called

a2 = A()
a2:f() -- the non-const version is called

a = A()
b = B()
c = C()

g(a) -- calls g(A*)
g(b) -- calls g(B*)
g(c) -- calls g(B*)

Calling Lua functions

To call a Lua function, you can either use call_function() or an object.

template<class Ret>
Ret call_function(lua_State* L, const char* name, ...)
template<class Ret>
Ret call_function(object const& obj, ...)

There are two overloads of the call_function function, one that calls a function given its name, and one that takes an object that should be a Lua value that can be called as a function.

The overload that takes a name can only call global Lua functions. The ... represents a variable number of parameters that are sent to the Lua function. This function call may throw luabind::error if the function call fails.

The return value isn’t actually Ret (the template parameter), but a proxy object that will do the function call. This enables you to give policies to the call. You do this with the operator[]. You give the policies within the brackets, like this:

int ret = call_function<int>(
    L
  , "a_lua_function"
  , new complex_class()
)[ adopt(_1) ];

If you want to pass a parameter as a reference, you have to wrap it with the Boost.Ref.

Like this:

int ret = call_function(L, "fun", boost::ref(val));

If you want to use a custom error handler for the function call, see set_pcall_callback under pcall errorfunc.

Using Lua threads

To start a Lua thread, you have to call lua_resume(), this means that you cannot use the previous function call_function() to start a thread. You have to use

template<class Ret>
Ret resume_function(lua_State* L, const char* name, ...)
template<class Ret>
Ret resume_function(object const& obj, ...)

and

template<class Ret>
Ret resume(lua_State* L, ...)

The first time you start the thread, you have to give it a function to execute. i.e. you have to use resume_function, when the Lua function yields, it will return the first value passed in to lua_yield(). When you want to continue the execution, you just call resume() on your lua_State, since it’s already executing a function, you don’t pass it one. The parameters to resume() will be returned by yield() on the Lua side.

For yielding C++-functions (without the support of passing data back and forth between the Lua side and the c++ side), you can use the yield policy.

With the overload of resume_function that takes an Object, it is important that the object was constructed with the thread as its lua_State*. Like this:

lua_State* thread = lua_newthread(L);
object fun = get_global(thread)["my_thread_fun"];
resume_function(fun);

Binding function objects with explicit signatures

Using luabind::tag_function<> it is possible to export function objects from which luabind can’t automatically deduce a signature. This can be used to slightly alter the signature of a bound function, or even to bind stateful function objects.

Synopsis:

template <class Signature, class F>
implementation-defined tag_function(F f);

Where Signature is a function type describing the signature of F. It can be used like this:

int f(int x);

// alter the signature so that the return value is ignored
def("f", tag_function<void(int)>(f));

struct plus
{
    plus(int x)
      : x(x)
    {}

    int operator()(int y) const
    {
        return x + y;
    }
};

// bind a stateful function object
def("plus3", tag_function<int(int)>(plus(3)));

Table Of Contents

Previous topic

Scopes

Next topic

Binding classes to Lua