2

I'm not sure if my question makes any sense, but I certainly know it is near impossible to get the results from Google. Firstly, what I do not want. I don't want to call some function that prints "hello world" or adds two numbers together, I want to load a Lua script from a C++ program, but allow the script to modify variables of the C++ program, using functions. For example, imagine I have a C++ program like this:

class Foo
{
    private:
        int number = 0;

    public:
        void setNumber(const int& newNumber) {number = newNumber;}
}

int main()
{
    Foo foo;

    //Load and execute Lua script, with foo object

    return 0;
}

How could I allow the Lua script to do foo.setNumber() (preferably without foo.)? This may be a very simple question, but as mentioned above, almost all information on Google when searching "Call C++ Function from Lua" assume there is no program, but just a .cpp/hpp file with some functions that you want to call.

I'm on Linux (Ubuntu), but the program needs to compile on all platforms (Windows and Mac)

6
  • rubenlaguna.com/wp/2012/12/09/accessing-cpp-objects-from-lua - the goal is to "access a C++ object". Commented Jul 17, 2015 at 21:12
  • I tried to answer but I realise it will be lengthy. Perhaps you should break down the scope to: 1) General LUA-C++ binding. 2) register class and methods to LUA. 3) LUA-OOP which enable you to use foo. in LUA. In short, it is quite common to do so, there are also some libraries . Commented Jul 17, 2015 at 21:39
  • 1
    There are any number of C++ libraries/etc. which handle binding objects/functions/etc. to lua for use in scripts. Have you tried searching for that? Have you looked at the lua-users.org wiki page on the topic? Commented Jul 17, 2015 at 21:42
  • @EtanReisner I've done some research on C++ libraries, but I prefer using the default Lua API (using libraries is usually more memory and stress just for prettier code). Commented Jul 17, 2015 at 22:03
  • 1
    A number of the libraries (and template magic instead of libraries) are specifically designed not to add much overhead. And you are welcome to do it yourself but they have already done it. So even if you don't use them they will show you how to do it. Commented Jul 17, 2015 at 22:17

1 Answer 1

4

This is asked here fairly regularly.

To roll your own binding you should:

  1. Master Lua metatables completely.
  2. Read the Programming in Lua stuff on the C API, particularly the part on classes. Alternatively you can read the manual, read the source (API headers especially), and do some googling, but the book will probably save you some time.

Broadly, you expose a C++ class instance to Lua by creating a Lua "userdata" containing a pointer to the class instance and passing this to the Lua script. A userdata is an opaque type; the Lua script can't actually do anything with it (other than pass it around) unless you give it a metatable. At the very least you must implement the __index metamethod on the userdata, which allows your C++ code to intercept attempts to index the userdata and return something meaningful, and the __gc metamethod, which allows your C++ code to delete the exposed C++ object when the corresponding Lua userdata is garbage collected.

For instance, you create a function called createFoo which creates a Foo instance, wraps the pointer as a userdata, applies a metatable implementing __index to it, and returns it to the Lua script.

When the user runs foo.setNumber, your C++ __index metamethod is called with the userdata and the string "setNumber". It's up to you what you return and this determines what foo.setNumber evaluates to in the Lua script. You want foo.setNumber to evaluate to a lua_CFunction which expects a Foo userdata as its first parameter, so that your class methods can be called idiomatically from Lua (i.e. foo:setNumber(12), which is syntax sugar for foo.setNumber(foo, 12)).

It's a very low level and manual process, and once you get the hang of it you're going to end up create a library/templates/macros whatever to do the boilerplate for you. At that point you may want to evaluate the myriad C++ binding libraries that exist. However, thanks to the Law of Leaky Abstractions it's a very good idea to learn to do this manually first.

Sign up to request clarification or add additional context in comments.

2 Comments

foo.setNumber will just access the metatable function but not pass the userdata. foo:setNumber(...) is the same as foo.setNumber(foo, ...) and the recommend way of calling class methods.
Yes. I deliberately avoided complicating that explanation, because o:m resolves to o:m(o), and it's the latter than we're actually worrying about in the C++ API. o.m should resolve to a lua_CFunction that expects a userdata as its first parameter, (assuming it's an instance method and not a static method). I'll clarify that above.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.