- Using Lua With SDL 2 - Example
- See Full List On Lucasklassmann.com
- Exposing C Functions To Lua - Sasank's Blog
- Lua Installation Guide
- Integrating Lua In C++ - GeeksforGeeks
EDIT: Part 2
Long time without posting, busy at work, family, etc.
Today I decided to write a bit on Lua and how to integrate it with C++.
Lua is a scripting language with an emphasis on being easily embeddable. Lua isused as the scripting language in Photoshop CS, and World of Warcraft, forexample. So if you are looking into adding scriptability to your C or C++applications Lua is quite suited for the task.
In order to learn Lua (both the language itself and how to embed it into yourapp) I recommend you Programming in Luaby one of the Luaauthors.
You can find tons of tutorials on how to get started with Lua. So I will focushere on how to integrate with C++. Most of the sources I’ve found about Lua -C++ integrations take the approach of frameworks to automatically wrap yourobjects/classes to be usable from within Lua. I find this approach confusing, Ithink it’s better to learn how to do it manually, and that’s what I will dohere.
Feb 28, 2021 I decided to create a folder called 'LuaConsole'. The full path would be, C: Program Files LuaConsole. Next, you want to set up LuaConsole so that you can just execute the program without specifying the path each time. This is trivial - just edit your environment variables.
Step 0. Compile Lua itself
Download Lua 5.2.1 and compile it. Usually it enough with make macosx
ormake linux
. That will generate liblua.a
, the library that we will link to.
Step 1. Create a simple host app
We need a simple host app. Our host app will simply setup Lua and run a scriptfrom it. This script will have access to a std::queue
from the host app. Thiswill illustrate how you can share objects with the Lua part. Later we will takea more complex example.
Let’s start with the basic skeleton of a lua environment with somecommunication with its host:
The Makefile
It uses LUAHOME
that should point to the directory containing both liblua.a
and the lua*.h
files.
The samplehost application
The Lua script
The code explained step by step:
Initialization
That creates a lua_State
loads the standard libs in it and also loads the code in luascript.lua
.
Adding variables from C++ into Lua
Then it sets a global variable in Lua from C++ code using lua_setglobal
. Ifyou don’t know what are the lua_pushxxxx
and the Lua stack, etc. I recomentthat you take a look at the Lua Reference Manual and Programming in Lua.More or less Lua and the C++ communicate through the stack that livesin lua_State
and there is bunch of function to manipulate that stack. So inorder to set a global in Lua from C++ you must push the value into the stackand call lua_setglobal
that will pop the value in the stack and assign it tothe identifier provided inside the Lua environment.
After setting the global cppvar
it executes the loaded chunk of code (that is in the stack) with lua_pcall
. The Lua code is able to read and print the value of cppvar
. The lua code will also set a new global luavar
that we will access from C++.
Reading a Lua variable from C++
To get luavar from C++, we must first uselua_getglobal
that will put the value associated with the identifier into the top of the stack and the lua_tonumber
will transform whatever it’s at the top of the stack into a double (well a luaNumber
) and then we can use that double in our C++ code to print it.Calling a Lua function from C++
The example won’t be complete without function calling so that’s the next step.Calling a Lua function from C++ it’s quite easy. Function in Lua are firstclass values, so that means that it’s just a like reading a any other value.lua_getglobal
will get the value and put it on the stack and then we push thefunction arguments into the stack and use lua_pcall
to call the function(that is the stack). The returned value from the function will be pushed in thestack and that’s were the C++ code will get it, lua_tostring
and then it willremove from the stack with lua_pop
.
Calling a C++ function from Lua
The other way around it’s more complex. You can’t just call any function fromLua. It has to has a special signature lua_CFunction
, that is, typedef int(*lua_CFunction) (lua_State *L)
a function that returns an int and takes alua_State
. This special funciton will communicate with Lua via the lua stackthat resides in the lua_State
parameter. The return value of the functiontell lua how many value the function has pushed into the stack as result valuesfor the function call.
So to make the function accesible from Lua, you create push the function intothe stack with lua_pushcfunction
and bind it to an identifier in lua withlua_setglobal
. Then lua code will be able to invoke this function like anyother function. In the example I call the myfunction
(which is lua code) andmyfunction
in turn invokes cppfunction
which is “bound” to C++l_cppfunction
. Ah, I almost forgot. l_cppfunction
is declared as extern'C'
telling the compiler to provide C linkage for this function so it can becalled from a C library like Lua is.
Free Lua resources
lua_close
will free all resources held by the lua_State
L.
Wrap up
I will leave the part on how to wrap C++ class objects inLua for a later post because Idon’t want to make this post too long. Hopefully I’ll post it tomorrow.
This is Part 1b of my Integrating Lua into C++ Tutorial series.
Now that we have everything set up, let’s start!
Running a simple Lua-code from c++
First off, let’s try doing something simple. Let’s try running a Lua code from a string.
This should print out:
Hello World!
Congratulations! You have run your first Lua-code in c++! As you can see, you don’t really need all these fancy ‘.lua’ files to run Lua-code. You can just use strings for the trivial stuffs.
You might be wondering what the code snippet above is doing.
sol::state state;
This line creates a lua state to be used in the codebase. Any functions or variables you define would ‘live in’ the state that it’s created in.
state.open_libraries(sol::lib::base, sol::lib::package);
This line loads up the default libraries that gives you certain functionalities of the Lua language. This includes I/O and other important functionalities. For our test case, we load up these libraries in order to run Lua’s print function.
If you are intending to create a sandbox for your game, you might not want to load up these libraries as you would essentially be giving your players too much power. You wouldn’t really want to give your modders functionalities to access I/O as it could lead to a security risk.
state.do_string('print('Hello World!')');
This line would run the Lua code snippet from a string. As you might guess, looking at the code, this line would print “Hello World!” to the console window.
Now let’s try running the same code snippet from a ‘.lua’ file.
In the default directory of your project, create a ‘scripts’ folder to store all your scripts.
Create a file ‘HelloWorld.lua’ in the script folder and add this code inside:
Now try running this code in c++:
This should also print out:
Hello World!
state.do_file('scripts/HelloWorld.lua');
You might notice the slight change of code here. Instead of do_script, we used do_file, to indicate that we want to run the code from a ‘.lua’ file instead of a string.
Accessing Lua variables from c++
In this part of the tutorial, we will be covering on how to access lua variables in c++ code.
Accessing lua variables from c++ is fairly simple.
Here we have a numeric lua variable named ‘luaNum’. As you can see, in the snippet code above, we are able to both set and get the value just like a normal variable in c++ just by knowing the lua variable’s name.
If nothing goes wrong, you’ll see:
printing in Lua: 3
printing in c++: 3
state['luaNum'] = 3;
This line defines a numeric lua value with the variable name of “luaNum”. As stated above, every time you reference “luaNum” in your lua codebase, you would be referencing this variable.
state.do_string(std::string('print('printing in Lua: ' .. luaNum)');
This line prints the value of “luaNum”. This might be off topic but “..” is the concatenation operator for strings in lua.
Running c++ functions from Lua
We shall first try calling c++ functions from lua. Right now we’ll only run normal functions. We shall look at classes later in part 2 of the tutorial.
Since we already covered that whatever we can do in the ‘.lua’ files can also be done using strings, we shall just cover the topic using strings in order to simplify the tutorial.
Let’s run this code!
If you run this code correctly, you should print out:
Called testCppFunction with return value (1)!
lua.set_function('testCppFunction', testCppFunction);
Using Lua With SDL 2 - Example
This lines binds the c++ function into the Lua state with the alias “testCppFunction”
state.do_string('num = testCppFunction(1); print(': Called testCppFunction! Return value:' .. num)');
This line calls the testCppFunction by calling “testCppFunction(1)” in the string.
You can also do this with functional objects, lambda, etc. Try it out!
Running Lua functions from c++
Before we do anything fancy like running the lua function from c++, let’s first run the code from a Lua file.
Create a Lua file called “testLuaFunction1.lua” in your scripts folder with the following code snippet:
If you did everything right, running this should print out “Calling testLuaFunction1!”.
In this lua file, we can see definition of the function testLuaFunction1 as well as a call to run the actual function.
Now let’s try running the Lua function from c++ code!
create a new lua file called ‘testLuaFunction2’ in your scripts folder with the following code snippet:
As you can see, the difference between this function and the previous function is that this function takes in a number and return said number + 10.
Alternatively, you can just remove the function call from ‘testLuaFunction1.lua’ and do all the tests by calling the function there.
See Full List On Lucasklassmann.com
There are multiple ways of calling a lua function from C++ code. Lets do the easiest way first. Im pretty sure that you already know how.
Exposing C Functions To Lua - Sasank's Blog
Well, you know the drill.
Running this code, you should get:
Calling testLuaFunction2 with input value (1)!
In the string, we used ‘1’ as the argument and as such, we printed ‘1’ as the prefix in the output.
Now we shall encapsulate the lua function into a c++ object and call the function in c++.
This should be pretty useful for you. Let’s do this!
Now you should get:
Calling testLuaFunction2 with input value (2)!
sol::function testLuaFunction2 = state['testLuaFunction2'];
This sol::function is a functional object referencing to the lua function “testLuaFunction2” in the lua state. Invoking the function would invoke the referenced lua function.
Nice, isn’t it? Now you can have a functional object in c++ behave like and look like a c++ function but is a lua function.
If you’ve really been observant, you would had noticed that ‘testLuaFunction2’ returns a value, more specifically the input value + 10.
Let’s try printing the return value of the function.
Now you should get:
Calling testLuaFunction2 with input value (1)!
Return value: 11
Calling testLuaFunction2 with input value (2)!
Return value: 12
Summary
This part of the tutorial is a lot longer than I wanted it to be. It’s also not so interesting but well, it’s a necessary evil as you need the knowledge here before you can continue on to the next part.
Codes:
main.cpp
HelloWorld.lua
Lua Installation Guide
testLuaFunction1.lua
Integrating Lua In C++ - GeeksforGeeks
testLuaFunction2.lua
Previous (Part 1a: Introduction and Setting Up) | Next(Part 2: Interacting with Classes)