Lua C API Guide — Embedding and Extending Lua in C Programs
In this tutorial, you will learn about Lua C API Guide. We cover key concepts, practical examples, and best practices to help you master this topic.
The Lua C API is the interface between C and Lua -- using a virtual stack to pass data between the two languages, enabling bidirectional communication for embedding Lua in applications or extending Lua with C libraries.
What You'll Learn
- The Lua stack model and how data flows between C and Lua
- Embedding Lua in a C program
- Exposing C functions to Lua
- Handling errors between the two languages
Why It Matters
The C API is what makes Lua embeddable. Games, security tools, and embedded systems use it to provide scripting in their applications. Durga Antivirus Pro embeds Lua through the C API to run user-defined threat detection rules in a sandboxed environment.
The Lua Stack
The C API communicates with Lua through a virtual stack. Values are pushed onto the stack by C, read by Lua, and vice versa.
#include <stdio.h>
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
int main() {
lua_State *L = luaL_newstate();
luaL_openlibs(L);
// Push values onto the stack
lua_pushnumber(L, 42);
lua_pushstring(L, "hello");
lua_pushboolean(L, 1);
// Read from stack
double num = lua_tonumber(L, -3);
const char *str = lua_tostring(L, -2);
int bool_val = lua_toboolean(L, -1);
printf("Stack values: %f, %s, %d\n", num, str, bool_val);
lua_close(L);
return 0;
}
Running Lua Scripts from C
#include <lua.h>
#include <lauxlib.h>
int main() {
lua_State *L = luaL_newstate();
luaL_openlibs(L);
// Run a Lua expression
if (luaL_dostring(L, "print('Hello from Lua!')") != LUA_OK) {
const char *err = lua_tostring(L, -1);
printf("Error: %s\n", err);
lua_pop(L, 1);
}
// Run a Lua file
if (luaL_dofile(L, "script.lua") != LUA_OK) {
const char *err = lua_tostring(L, -1);
printf("Error: %s\n", err);
lua_pop(L, 1);
}
lua_close(L);
return 0;
}
Calling Lua Functions from C
// Assume Lua has: function add(a, b) return a + b end
lua_getglobal(L, "add"); // push function
lua_pushnumber(L, 10); // push argument 1
lua_pushnumber(L, 20); // push argument 2
if (lua_pcall(L, 2, 1, 0) != LUA_OK) {
const char *err = lua_tostring(L, -1);
printf("Error: %s\n", err);
} else {
double result = lua_tonumber(L, -1);
printf("Result: %f\n", result); // 30
lua_pop(L, 1); // pop result
}
Exposing C Functions to Lua
// C function to expose
static int c_add(lua_State *L) {
double a = luaL_checknumber(L, 1);
double b = luaL_checknumber(L, 2);
lua_pushnumber(L, a + b);
return 1; // number of return values
}
// Register with Lua
lua_register(L, "add", c_add);
// Now Lua can call: add(10, 20) -> 30
Error Handling
// Using protected calls
if (lua_pcall(L, nargs, nresults, msgh) != LUA_OK) {
const char *msg = lua_tostring(L, -1);
fprintf(stderr, "Lua error: %s\n", msg);
lua_pop(L, 1); // remove error message
return 0;
}
Common Mistakes
1. Stack leaks
Every push must be matched by a pop. Not balancing the stack causes memory growth.
2. Forgetting to check types
Always use luaL_check* functions to validate argument types. Without them, invalid input causes undefined behavior.
3. Using negative indices incorrectly
Negative indices count from the top (-1 = top). Positive indices count from the bottom (1 = bottom). Know which you're using.
4. Not checking pcall return
lua_pcall can fail. Always check the return value and handle errors.
5. Memory management
Lua's garbage collector doesn't know about C allocations. Use proper cleanup or risk memory leaks.
Practice Questions
1. What is the Lua stack? A virtual stack used for all communication between C and Lua. Values are pushed by one side and read by the other.
2. How do you call a Lua function from C? Push the function onto the stack, push arguments, call lua_pcall, then read results from the stack.
3. What does lua_pcall return on success vs error? Returns LUA_OK on success. Returns LUA_ERRRUN, LUA_ERRMEM, or LUA_ERRERR on errors.
FAQ
{{< faq question="Do I need to know C to use Lua?" >}} No. The C API is only needed when embedding Lua in C applications or writing C extension modules. Most Lua users never touch the C API. {{< /faq >}}
{{< faq question="Can I use the C API from C++?" >}}
Yes. The Lua headers work with C++. Compile with a C++ compiler, or wrap C headers in extern "C" {}.
{{< /faq >}}
{{< faq question="What is lua_State?" >}} The main state object representing a Lua Interpreter instance. Each Lua VM has one lua_State. Multiple states are independent. {{< /faq >}}
{{< faq question="Can multiple C threads share one Lua state?" >}} No. Lua states are not thread-safe. Use one state per thread, or use Lua's built-in coroutines for concurrency within one state. {{< /faq >}}
{{< faq question="What is LuaJIT's FFI?" >}} LuaJIT's FFI (Foreign Function Interface) lets you call C functions directly from Lua without writing C wrapper code. It's much simpler than the standard C API for many use cases. {{< /faq >}}
What's Next
Now that you understand the C API, apply your Lua skills to Game Development with Love2D.
| Topic | Description | Link |
|---|---|---|
| Love2D | Game development framework | {{< ref "12-love2d" >}} |
| LuaRocks | Package manager | {{< ref "13-luarocks" >}} |
| C | Compare with standard C Programming | C |
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro