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 theaddfunction 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_functionin 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 asmultiplyin 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
 
