The Lua C API allows you to extend Lua with functions written in C, and to embed Lua into C programs. This module will guide you through the basics of using the Lua C API, providing practical examples and exercises to help you understand how to integrate Lua with C.
Key Concepts
- Lua State: The central structure used to manage all Lua-related data.
- Stack Operations: Functions to manipulate the Lua stack.
- Calling Lua Functions from C: How to call Lua functions from C code.
- Registering C Functions in Lua: How to make C functions available to Lua scripts.
- Error Handling: Managing errors when calling Lua from C.
Lua State
The Lua state (lua_State
) is a structure that represents a Lua interpreter. It holds all the information about the execution of Lua code, including global variables, the stack, and the environment.
Example: Creating a Lua State
#include <lua.h> #include <lualib.h> #include <lauxlib.h> int main() { lua_State *L = luaL_newstate(); // Create a new Lua state luaL_openlibs(L); // Open the standard libraries // Your code here lua_close(L); // Close the Lua state return 0; }
Explanation
luaL_newstate()
: Creates a new Lua state.luaL_openlibs(L)
: Opens the standard Lua libraries (e.g., base, table, string).lua_close(L)
: Closes the Lua state and frees all associated resources.
Stack Operations
Lua uses a stack to pass values between C and Lua. The stack is a central concept in the Lua C API.
Example: Pushing and Popping Values
#include <lua.h> #include <lualib.h> #include <lauxlib.h> int main() { lua_State *L = luaL_newstate(); luaL_openlibs(L); lua_pushnumber(L, 10); // Push a number onto the stack lua_pushstring(L, "Hello, Lua!"); // Push a string onto the stack double num = lua_tonumber(L, -2); // Get the number from the stack const char *str = lua_tostring(L, -1); // Get the string from the stack printf("Number: %f\n", num); printf("String: %s\n", str); lua_pop(L, 2); // Pop two values from the stack lua_close(L); return 0; }
Explanation
lua_pushnumber(L, 10)
: Pushes the number 10 onto the stack.lua_pushstring(L, "Hello, Lua!")
: Pushes the string "Hello, Lua!" onto the stack.lua_tonumber(L, -2)
: Retrieves the number from the second-to-last position on the stack.lua_tostring(L, -1)
: Retrieves the string from the last position on the stack.lua_pop(L, 2)
: Pops the top two values from the stack.
Calling Lua Functions from C
You can call Lua functions from C by pushing the function and its arguments onto the stack and then using lua_pcall
.
Example: Calling a Lua Function
#include <lua.h> #include <lualib.h> #include <lauxlib.h> int main() { lua_State *L = luaL_newstate(); luaL_openlibs(L); luaL_dostring(L, "function add(a, b) return a + b end"); // Define a Lua function lua_getglobal(L, "add"); // Push the function onto the stack lua_pushnumber(L, 5); // Push the first argument lua_pushnumber(L, 3); // Push the second argument if (lua_pcall(L, 2, 1, 0) != LUA_OK) { // Call the function with 2 arguments and 1 result printf("Error: %s\n", lua_tostring(L, -1)); lua_pop(L, 1); } else { double result = lua_tonumber(L, -1); // Get the result printf("Result: %f\n", result); lua_pop(L, 1); } lua_close(L); return 0; }
Explanation
luaL_dostring(L, "function add(a, b) return a + b end")
: Defines a Lua function.lua_getglobal(L, "add")
: Pushes theadd
function onto the stack.lua_pushnumber(L, 5)
: Pushes the first argument (5) onto the stack.lua_pushnumber(L, 3)
: Pushes the second argument (3) onto the stack.lua_pcall(L, 2, 1, 0)
: Calls the function with 2 arguments and expects 1 result.lua_tonumber(L, -1)
: Retrieves the result from the stack.
Registering C Functions in Lua
You can make C functions available to Lua by registering them.
Example: Registering a C Function
#include <lua.h> #include <lualib.h> #include <lauxlib.h> int my_c_function(lua_State *L) { double a = lua_tonumber(L, 1); double b = lua_tonumber(L, 2); lua_pushnumber(L, a + b); return 1; // Number of return values } int main() { lua_State *L = luaL_newstate(); luaL_openlibs(L); lua_register(L, "my_c_function", my_c_function); // Register the C function luaL_dostring(L, "result = my_c_function(10, 20)"); // Call the C function from Lua lua_getglobal(L, "result"); double result = lua_tonumber(L, -1); printf("Result: %f\n", result); lua_close(L); return 0; }
Explanation
my_c_function(lua_State *L)
: Defines a C function that adds two numbers.lua_register(L, "my_c_function", my_c_function)
: Registers the C function asmy_c_function
in Lua.luaL_dostring(L, "result = my_c_function(10, 20)")
: Calls the C function from Lua.lua_getglobal(L, "result")
: Retrieves the result from the Lua global environment.
Error Handling
Error handling in the Lua C API is done using lua_pcall
and checking its return value.
Example: Error Handling
#include <lua.h> #include <lualib.h> #include <lauxlib.h> int main() { lua_State *L = luaL_newstate(); luaL_openlibs(L); if (luaL_dofile(L, "non_existent_file.lua") != LUA_OK) { printf("Error: %s\n", lua_tostring(L, -1)); lua_pop(L, 1); } lua_close(L); return 0; }
Explanation
luaL_dofile(L, "non_existent_file.lua")
: Attempts to execute a Lua file.lua_tostring(L, -1)
: Retrieves the error message from the stack.lua_pop(L, 1)
: Pops the error message from the stack.
Practical Exercise
Exercise: Integrate a C Function with Lua
- Write a C function that multiplies two numbers.
- Register this function in Lua.
- Call the function from a Lua script and print the result.
Solution
#include <lua.h> #include <lualib.h> #include <lauxlib.h> int multiply(lua_State *L) { double a = lua_tonumber(L, 1); double b = lua_tonumber(L, 2); lua_pushnumber(L, a * b); return 1; } int main() { lua_State *L = luaL_newstate(); luaL_openlibs(L); lua_register(L, "multiply", multiply); luaL_dostring(L, "result = multiply(10, 20)"); lua_getglobal(L, "result"); double result = lua_tonumber(L, -1); printf("Result: %f\n", result); lua_close(L); return 0; }
Explanation
multiply(lua_State *L)
: Defines a C function that multiplies two numbers.lua_register(L, "multiply", multiply)
: Registers the C function asmultiply
in Lua.luaL_dostring(L, "result = multiply(10, 20)")
: Calls the C function from Lua.lua_getglobal(L, "result")
: Retrieves the result from the Lua global environment.
Conclusion
In this section, you learned how to use the Lua C API to integrate Lua with C. You covered the basics of creating a Lua state, manipulating the stack, calling Lua functions from C, registering C functions in Lua, and handling errors. These skills are essential for extending Lua with custom functionality and embedding Lua into C applications.
Lua Programming Course
Module 1: Introduction to Lua
Module 2: Basic Concepts
Module 3: Intermediate Concepts
Module 4: Advanced Concepts
- Coroutines
- Object-Oriented Programming in Lua
- Debugging Techniques
- Performance Optimization
- Using the Lua C API
Module 5: Practical Applications
- Building a Simple Game
- Scripting in Game Engines
- Automating Tasks with Lua
- Integrating Lua with Other Languages