Lua 与 C/C++ 集成实战

本章教你如何将 Lua 嵌入到 C 和 C++ 项目中,实现多语言混合编程。这是 Lua 最核心的应用场景。


第1节:基本原理

Lua 虚拟栈

C/C++ 与 Lua 之间通过一个虚拟栈来交换数据。所有数据传递都在栈上进行:

Lua 脚本 ←─────── 虚拟栈 ───────→ C/C++ 代码
 push / pop / get top
栈索引类型说明
正索引栈底 = 1, 向上递增 → lua_gettop(L)
负索引栈顶 = -1, 向下递减 → -1, -2, -3...

编译依赖

# 安装开发包(包含头文件和库)
# Ubuntu/Debian
sudo apt install liblua5.4-dev
 
# Arch
sudo pacman -S lua
 
# macOS
brew install lua
 
# 编译时需要链接:
# C: gcc -o app app.c -llua -lm -ldl
# C++: g++ -o app app.cpp -llua -lm -ldl
# # 如果是 LuaJIT: -lluajit-5.1

第2节:C 语言嵌入 Lua 完整示例

示例1:C 调用 Lua 脚本

Lua 脚本 calcs.lua

-- calcs.lua
local calcs = {}
 
function calcs.add(a, b)
 return a + b
end
 
function calcs.multiply(a, b)
 return a * b
end
 
function calcs.getInfo()
 return "Lua 5.4", 100, true
end
 
return calcs

C 代码 main.c

#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
#include <stdio.h>
 
int main() {
 // 1. 创建 Lua 虚拟机
 lua_State* L = luaL_newstate();
 
 // 2. 加载标准库
 luaL_openlibs(L);
 
 // 3. 执行 Lua 脚本
 if (luaL_dofile(L, "calcs.lua") != LUA_OK) {
 fprintf(stderr, "错误: %s\n", lua_tostring(L, -1));
 lua_close(L);
 return 1;
 }
 
 // 现在脚本中的 calcs 表在栈顶(因为 return calcs)
 
 // ---- 调用 calcs.add(10, 20) ----
 lua_getfield(L, -1, "add"); // 压入 add 函数
 lua_pushinteger(L, 10); // 压入参数1
 lua_pushinteger(L, 20); // 压入参数2
 
 if (lua_pcall(L, 2, 1, 0) == LUA_OK) { // 2参数, 1返回值
 lua_Integer result = lua_tointeger(L, -1);
 printf("add(10, 20) = %lld\n", (long long)result);
 lua_pop(L, 1); // 弹出返回值
 }
 
 // ---- 调用 calcs.multiply(7, 8) ----
 lua_getfield(L, -1, "multiply");
 lua_pushinteger(L, 7);
 lua_pushinteger(L, 8);
 lua_pcall(L, 2, 1, 0);
 printf("multiply(7, 8) = %lld\n", (long long)lua_tointeger(L, -1));
 lua_pop(L, 1);
 
 // ---- 调用 calcs.getInfo() 多返回值 ----
 lua_getfield(L, -1, "getInfo");
 lua_pcall(L, 0, 3, 0); // 0参数, 3返回值
 
 const char* name = lua_tostring(L, -3);
 lua_Integer val = lua_tointeger(L, -2);
 int ok = lua_toboolean(L, -1);
 
 printf("getInfo() -> %s, %lld, %d\n", name, (long long)val, ok);
 lua_pop(L, 3); // 弹出3个返回值
 
 // 4. 清理
 lua_close(L);
 return 0;
}

编译与运行

gcc -o main main.c -llua -lm -ldl
./main

输出:

add(10, 20) = 30
multiply(7, 8) = 56
getInfo() -> Lua 5.4, 100, 1

示例2:Lua 调用 C 函数 — 注册自定义函数

C 代码 c_math.c

#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
#include <stdio.h>
#include <math.h>
 
// C 函数签名: int (*)(lua_State*)
// 参数从栈中获取,返回值也压入栈中
 
// ---- 自定义函数1: 计算两点距离 ----
static int l_distance(lua_State* L) {
 double x1 = luaL_checknumber(L, 1); // 第1个参数
 double y1 = luaL_checknumber(L, 2); // 第2个参数
 double x2 = luaL_checknumber(L, 3); // 第3个参数
 double y2 = luaL_checknumber(L, 4); // 第4个参数
 
 double dx = x2 - x1;
 double dy = y2 - y1;
 double dist = sqrt(dx * dx + dy * dy);
 
 lua_pushnumber(L, dist); // 压入返回值
 return 1; // 返回值个数
}
 
// ---- 自定义函数2: 返回多个值 ----
static int l_min_max(lua_State* L) {
 int n = lua_gettop(L); // 参数个数
 if (n < 1) {
 lua_pushnil(L);
 lua_pushnil(L);
 return 2;
 }
 
 double min = lua_tonumber(L, 1);
 double max = lua_tonumber(L, 1);
 
 for (int i = 2; i <= n; i++) {
 double val = lua_tonumber(L, i);
 if (val < min) min = val;
 if (val > max) max = val;
 }
 
 lua_pushnumber(L, min);
 lua_pushnumber(L, max);
 return 2; // 返回两个值
}
 
// ---- 注册函数映射表 ----
static const struct luaL_Reg mylib[] = {
 {"distance", l_distance},
 {"minmax", l_min_max},
 {NULL, NULL} // 终止标记
};
 
// ---- 库入口: 会被 require("c_math") 调用 ----
int luaopen_c_math(lua_State* L) {
 luaL_newlib(L, mylib);
 return 1;
}
 
// ---- 主程序入口 ----
int main() {
 lua_State* L = luaL_newstate();
 luaL_openlibs(L);
 
 // 注册 C 模块
 luaL_requiref(L, "c_math", luaopen_c_math, 1);
 lua_pop(L, 1);
 
 // 执行 Lua 脚本
 if (luaL_dofile(L, "app.lua") != LUA_OK) {
 fprintf(stderr, "错误: %s\n", lua_tostring(L, -1));
 }
 
 lua_close(L);
 return 0;
}

Lua 脚本 app.lua

local cmath = require("c_math")
 
local dist = cmath.distance(0, 0, 3, 4)
print("距离: " .. dist) -- 距离: 5.0
 
local min, max = cmath.minmax(3, 7, 2, 9, 1, 5)
print("最小: " .. min .. ", 最大: " .. max) -- 最小: 1, 最大: 9

编译

gcc -o c_math c_math.c -llua -lm -ldl
./c_math

示例3:完整应用 — C 控制台游戏框架

一个使用 C 实现核心逻辑、Lua 编写游戏脚本的示例。

Lua 脚本 game.lua

-- 游戏配置(由 C 程序读取)
local config = {
 title = "我的游戏",
 width = 800,
 height = 600,
 fps = 60,
}
 
function config.onInit()
 print("游戏初始化...")
end
 
function config.onUpdate(dt)
 print(string.format("帧更新: dt=%.3f秒", dt))
end
 
function config.onKeyDown(key)
 if key == "escape" then
 print("按下了 ESC,退出游戏")
 return "quit"
 elseif key == "space" then
 print("按下了空格,跳跃!")
 return "jump"
 end
end
 
function config.onShutdown()
 print("游戏关闭,清理资源...")
end
 
return config

C 代码 game_engine.c

#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
#include <stdio.h>
#include <unistd.h> // usleep
 
int main() {
 lua_State* L = luaL_newstate();
 luaL_openlibs(L);
 
 // 加载游戏脚本
 if (luaL_dofile(L, "game.lua") != LUA_OK) {
 fprintf(stderr, "错误: %s\n", lua_tostring(L, -1));
 lua_close(L);
 return 1;
 }
 
 // ---- 读取配置 ----
 lua_getfield(L, -1, "title");
 const char* title = lua_tostring(L, -1);
 lua_pop(L, 1);
 
 lua_getfield(L, -1, "width");
 lua_getfield(L, -1, "height");
 int width = lua_tointeger(L, -2);
 int height = lua_tointeger(L, -1);
 lua_pop(L, 2);
 
 printf("游戏: %s (%dx%d)\n", title, width, height);
 
 // ---- 调用 onInit ----
 lua_getfield(L, -1, "onInit");
 lua_pcall(L, 0, 0, 0);
 
 // ---- 模拟游戏循环 (1秒) ----
 lua_getfield(L, -1, "fps");
 int fps = lua_tointeger(L, -1);
 lua_pop(L, 1);
 
 double dt = 1.0 / fps;
 for (int frame = 0; frame < 3; frame++) {
 lua_getfield(L, -1, "onUpdate");
 lua_pushnumber(L, dt);
 lua_pcall(L, 1, 0, 0);
 usleep(1000000 / fps); // 模拟帧间隔
 }
 
 // ---- 模拟按键 ----
 lua_getfield(L, -1, "onKeyDown");
 lua_pushstring(L, "space");
 lua_pcall(L, 1, 1, 0);
 const char* action = lua_tostring(L, -1);
 printf("按键结果: %s\n", action);
 lua_pop(L, 1);
 
 // ---- 调用 onShutdown ----
 lua_getfield(L, -1, "onShutdown");
 lua_pcall(L, 0, 0, 0);
 
 lua_close(L);
 printf("游戏结束\n");
 return 0;
}

编译运行

gcc -o game_engine game_engine.c -llua -lm -ldl
./game_engine

第3节:C++ 嵌入 Lua 完整示例

示例4:C++ 封装 Lua 调用

现代 C++ 封装 LuaContext.hpp

#ifndef LUA_CONTEXT_HPP
#define LUA_CONTEXT_HPP
 
#include <lua.hpp> // C++ 包装头文件(使用 extern "C")
#include <string>
#include <functional>
#include <stdexcept>
 
class LuaContext {
private:
 lua_State* L;
 
public:
 LuaContext() {
 L = luaL_newstate();
 luaL_openlibs(L);
 }
 
 ~LuaContext() {
 if (L) lua_close(L);
 }
 
 // 禁止拷贝
 LuaContext(const LuaContext&) = delete;
 LuaContext& operator=(const LuaContext&) = delete;
 
 lua_State* getState() { return L; }
 
 // 执行脚本文件
 void doFile(const std::string& filename) {
 if (luaL_dofile(L, filename.c_str()) != LUA_OK) {
 std::string err = lua_tostring(L, -1);
 lua_pop(L, 1);
 throw std::runtime_error("Lua错误: " + err);
 }
 }
 
 // 执行脚本字符串
 void doString(const std::string& code) {
 if (luaL_dostring(L, code.c_str()) != LUA_OK) {
 std::string err = lua_tostring(L, -1);
 lua_pop(L, 1);
 throw std::runtime_error("Lua错误: " + err);
 }
 }
 
 // 注册 C++ 函数到 Lua
 void registerFunction(const std::string& name, lua_CFunction func) {
 lua_register(L, name.c_str(), func);
 }
 
 // 注册 C++ lambda 函数到 Lua
 // (需要模板处理,见下方完整示例)
};
 
#endif

C++ 完整应用 cpp_main.cpp

#include <lua.hpp>
#include <iostream>
#include <string>
#include <vector>
#include <functional>
#include <stdexcept>
 
// ---------- Lua 状态管理器 ----------
class LuaState {
private:
 lua_State* L;
 
public:
 LuaState() : L(luaL_newstate()) {
 luaL_openlibs(L);
 }
 
 ~LuaState() { if (L) lua_close(L); }
 
 LuaState(const LuaState&) = delete;
 LuaState& operator=(const LuaState&) = delete;
 
 lua_State* get() { return L; }
 
 void doFile(const std::string& file) {
 if (luaL_dofile(L, file.c_str()) != LUA_OK) {
 std::string err = lua_tostring(L, -1);
 lua_pop(L, 1);
 throw std::runtime_error(err);
 }
 }
};
 
// ---------- 向量类 ----------
struct Vector3 {
 double x, y, z;
 Vector3(double x = 0, double y = 0, double z = 0) : x(x), y(y), z(z) {}
 
 double length() const { return std::sqrt(x*x + y*y + z*z); }
 
 void print() const {
 std::cout << "Vector3(" << x << ", " << y << ", " << z << ") length=" << length() << std::endl;
 }
};
 
// ---------- C++ 暴露给 Lua 的函数 ----------
 
// 函数1: 计算向量长度 —— C++ 接收 Lua 的表,计算并返回
static int cpp_vectorLength(lua_State* L) {
 luaL_checktype(L, 1, LUA_TTABLE);
 
 lua_getfield(L, 1, "x");
 lua_getfield(L, 1, "y");
 lua_getfield(L, 1, "z");
 
 double x = lua_tonumber(L, -3);
 double y = lua_tonumber(L, -2);
 double z = lua_tonumber(L, -1);
 
 lua_pop(L, 3);
 
 double len = std::sqrt(x*x + y*y + z*z);
 lua_pushnumber(L, len);
 return 1;
}
 
// 函数2: C++ 创建并返回 Lua 表
static int cpp_createVector(lua_State* L) {
 double x = luaL_optnumber(L, 1, 0.0);
 double y = luaL_optnumber(L, 2, 0.0);
 double z = luaL_optnumber(L, 3, 0.0);
 
 lua_newtable(L); // 创建表
 lua_pushnumber(L, x); // 值
 lua_setfield(L, -2, "x"); // 设置为 t.x = x
 lua_pushnumber(L, y);
 lua_setfield(L, -2, "y");
 lua_pushnumber(L, z);
 lua_setfield(L, -2, "z");
 
 return 1; // 返回表
}
 
// 函数3: C++ 获取 Lua 全局变量并修改
static int cpp_modifyGlobal(lua_State* L) {
 const char* varName = luaL_checkstring(L, 1);
 double delta = luaL_checknumber(L, 2);
 
 lua_getglobal(L, varName);
 if (lua_isnumber(L, -1)) {
 double val = lua_tonumber(L, -1);
 lua_pop(L, 1);
 
 lua_pushnumber(L, val + delta);
 lua_setglobal(L, varName);
 
 lua_pushboolean(L, 1);
 return 1;
 }
 
 lua_pushboolean(L, 0);
 return 1;
}
 
// ---------- 主程序 ----------
int main() {
 try {
 LuaState lua;
 
 // 注册 C++ 函数到 Lua
 lua_register(lua.get(), "vec_length", cpp_vectorLength);
 lua_register(lua.get(), "vec_create", cpp_createVector);
 lua_register(lua.get(), "modify_global", cpp_modifyGlobal);
 
 // 执行 Lua 代码
 const char* script = R"(
 -- Lua 调用 C++ 函数创建向量
 local v = vec_create(3, 4, 0)
 print("创建的向量:", v.x, v.y, v.z)
 
 -- Lua 调用 C++ 函数计算长度
 local len = vec_length({x=6, y=8, z=0})
 print("向量长度:", len)
 
 -- Lua 设置全局变量
 score = 100
 print("修改前 score:", score)
 
 -- C++ 修改 Lua 全局变量
 local ok = modify_global("score", 50)
 print("修改结果:", ok)
 print("修改后 score:", score)
 
 -- Lua 原生计算
 local function dot(a, b)
 return a.x * b.x + a.y * b.y + a.z * b.z
 end
 
 local v1 = {x=1, y=2, z=3}
 local v2 = {x=4, y=5, z=6}
 print("点积:", dot(v1, v2))
 )";
 
 luaL_dostring(lua.get(), script);
 
 } catch (const std::exception& e) {
 std::cerr << "错误: " << e.what() << std::endl;
 return 1;
 }
 
 return 0;
}

编译

g++ -std=c++17 -o cpp_main cpp_main.cpp -llua -lm -ldl
./cpp_main

输出:

创建的向量: 3 4 0
向量长度: 10.0
修改前 score: 100
修改结果: true
修改后 score: 150
点积: 32

示例5:C++ 玩家系统 — C++ 数据 + Lua 行为

一个更贴近实际的例子:C++ 管理玩家数据,Lua 定义 AI 行为。

C++ 代码 player_ai.cpp

#include <lua.hpp>
#include <iostream>
#include <string>
#include <vector>
#include <cmath>
#include <memory>
 
// ---------- C++ 玩家类 ----------
class Player {
public:
 std::string name;
 double x, y;
 double hp;
 double maxHp;
 
 Player(std::string name, double x, double y, double hp)
 : name(std::move(name)), x(x), y(y), hp(hp), maxHp(hp) {}
 
 void move(double dx, double dy) {
 x += dx;
 y += dy;
 }
 
 void takeDamage(double dmg) {
 hp = std::max(0.0, hp - dmg);
 }
 
 void heal(double amount) {
 hp = std::min(maxHp, hp + amount);
 }
 
 bool isAlive() const { return hp > 0; }
 
 double distanceTo(double tx, double ty) const {
 return std::sqrt((tx - x) * (tx - x) + (ty - y) * (ty - y));
 }
};
 
// ---------- 将 C++ Player 暴露给 Lua ----------
 
// 宏简化操作: 从栈中获取 Player*
#define PLAYER(L) (*static_cast<Player**>(luaL_checkudata(L, 1, "Player")))
 
static int player_move(lua_State* L) {
 auto& p = *PLAYER(L);
 double dx = luaL_checknumber(L, 2);
 double dy = luaL_checknumber(L, 3);
 p.move(dx, dy);
 return 0;
}
 
static int player_getHp(lua_State* L) {
 auto& p = *PLAYER(L);
 lua_pushnumber(L, p.hp);
 return 1;
}
 
static int player_takeDamage(lua_State* L) {
 auto& p = *PLAYER(L);
 double dmg = luaL_checknumber(L, 2);
 p.takeDamage(dmg);
 lua_pushboolean(L, p.isAlive());
 return 1;
}
 
static int player_distanceTo(lua_State* L) {
 auto& p = *PLAYER(L);
 double tx = luaL_checknumber(L, 2);
 double ty = luaL_checknumber(L, 3);
 lua_pushnumber(L, p.distanceTo(tx, ty));
 return 1;
}
 
static int player_getName(lua_State* L) {
 auto& p = *PLAYER(L);
 lua_pushstring(L, p.name.c_str());
 return 1;
}
 
// 元方法索引表
static const luaL_Reg player_methods[] = {
 {"move", player_move},
 {"getHp", player_getHp},
 {"takeDamage", player_takeDamage},
 {"distanceTo", player_distanceTo},
 {"getName", player_getName},
 {NULL, NULL}
};
 
// 创建 Player userdata
static int player_new(lua_State* L) {
 std::string name = luaL_checkstring(L, 1);
 double x = luaL_checknumber(L, 2);
 double y = luaL_checknumber(L, 3);
 double hp = luaL_checknumber(L, 4);
 
 auto* pp = static_cast<Player**>(
 lua_newuserdata(L, sizeof(Player*))
 );
 *pp = new Player(name, x, y, hp);
 
 // 设置元表
 luaL_getmetatable(L, "Player");
 lua_setmetatable(L, -2);
 
 return 1;
}
 
void registerPlayer(lua_State* L) {
 // 创建 Player 元表
 luaL_newmetatable(L, "Player");
 
 // __index = 方法表
 lua_pushstring(L, "__index");
 lua_newtable(L);
 luaL_setfuncs(L, player_methods, 0);
 lua_settable(L, -3);
 
 // __gc 析构函数
 lua_pushstring(L, "__gc");
 lua_pushcfunction(L, [](lua_State* L) -> int {
 auto* pp = static_cast<Player**>(luaL_checkudata(L, 1, "Player"));
 delete *pp;
 return 0;
 });
 lua_settable(L, -3);
 
 // __tostring
 lua_pushstring(L, "__tostring");
 lua_pushcfunction(L, [](lua_State* L) -> int {
 auto& p = *PLAYER(L);
 lua_pushfstring(L, "Player(%s, hp=%.0f, pos=(%.0f,%.0f))",
 p.name.c_str(), p.hp, p.x, p.y);
 return 1;
 });
 lua_settable(L, -3);
 
 lua_pop(L, 1);
 
 // 注册全局构造函数 Player.new()
 lua_register(L, "Player", player_new);
}
 
// ---------- 主程序 ----------
int main() {
 lua_State* L = luaL_newstate();
 luaL_openlibs(L);
 
 // 注册 Player 类
 registerPlayer(L);
 
 // 注册辅助函数
 lua_register(L, "RandomRange", [](lua_State* L) -> int {
 double min = luaL_checknumber(L, 1);
 double max = luaL_checknumber(L, 2);
 lua_pushnumber(L, min + (rand() / (double)RAND_MAX) * (max - min));
 return 1;
 });
 
 srand(time(nullptr));
 
 // Lua AI 脚本
 const char* script = R"(
 -- 创建两个玩家
 local hero = Player("勇士", 0, 0, 200)
 local enemy = Player("巨魔", 50, 0, 150)
 
 print("战斗开始!")
 print(tostring(hero))
 print(tostring(enemy))
 
 -- 战斗循环
 local function battle()
 while hero:getHp() > 0 and enemy:getHp() > 0 do
 -- 英雄攻击
 local dist = hero:distanceTo(enemy.x, enemy.y)
 if dist <= 10 then
 local dmg = RandomRange(15, 25)
 print(string.format("%s 攻击 %s,造成 %.0f 伤害",
 hero:getName(), enemy:getName(), dmg))
 enemy:takeDamage(dmg)
 else
 hero:move(5, 0) -- 靠近敌人
 print(hero:getName() .. " 靠近敌人")
 end
 
 -- 敌人反击
 if enemy:getHp() > 0 then
 local dmg = RandomRange(10, 20)
 print(string.format("%s 反击 %s,造成 %.0f 伤害",
 enemy:getName(), hero:getName(), dmg))
 hero:takeDamage(dmg)
 end
 end
 
 -- 判断胜负
 if hero:getHp() > 0 then
 print(hero:getName() .. " 获得胜利!剩余血量: " .. hero:getHp())
 else
 print(enemy:getName() .. " 获得胜利!剩余血量: " .. enemy:getHp())
 end
 end
 
 battle()
 )";
 
 if (luaL_dostring(L, script) != LUA_OK) {
 std::cerr << "Lua错误: " << lua_tostring(L, -1) << std::endl;
 }
 
 lua_close(L);
 return 0;
}

编译运行

g++ -std=c++17 -o player_ai player_ai.cpp -llua -lm -ldl
./player_ai

第4节:C/C++ API 速查表

压栈(Push)

C API说明
lua_pushnil(L)压入 nil
lua_pushboolean(L, b)压入布尔值
lua_pushnumber(L, n)压入浮点数
lua_pushinteger(L, n)压入整数
lua_pushstring(L, s)压入字符串
lua_pushcfunction(L, f)压入 C 函数
lua_newtable(L)压入新表
lua_newuserdata(L, sz)压入用户数据(sz 字节)

取值(Get / Check)

C API说明
lua_toboolean(L, idx)获取布尔值
lua_tonumber(L, idx)获取浮点数
lua_tointeger(L, idx)获取整数
lua_tostring(L, idx)获取字符串(返回的指针可能失效)
lua_touserdata(L, idx)获取用户数据
luaL_checknumber(L, idx)检查并获取数字(类型不符则报错)
luaL_checkstring(L, idx)检查并获取字符串

表操作

C API说明
lua_getfield(L, idx, key)t[k] 压入栈
lua_setfield(L, idx, key)t[k] = v
lua_gettable(L, idx)t[k](k 在栈顶)
lua_settable(L, idx)t[k] = v(k 在栈顶-1, v 在栈顶)
lua_geti(L, idx, n)t[n] 压入栈
lua_seti(L, idx, n)t[n] = v
lua_rawget(L, idx)不触发元方法的 gettable
lua_rawset(L, idx)不触发元方法的 settable

全局变量

C API说明
lua_getglobal(L, name)获取全局变量压入栈
lua_setglobal(L, name)设置全局变量(从栈顶取值)

调用

C API说明
lua_call(L, nargs, nresults)直接调用(不保护)
lua_pcall(L, nargs, nresults, errfunc)保护调用
luaL_dofile(L, file)执行 Lua 文件
luaL_dostring(L, str)执行 Lua 字符串

模块

C API说明
luaL_newlib(L, funcs)创建模块表
luaL_setfuncs(L, funcs, nup)批量注册函数
luaL_requiref(L, name, fn, glb)注册 require 可用模块

第5节:编译配置

Makefile 模板

CC = gcc
CXX = g++
LUA_CFLAGS = $(shell pkg-config --cflags lua 2>/dev/null || echo "-I/usr/include/lua5.4")
LUA_LIBS = $(shell pkg-config --libs lua 2>/dev/null || echo "-llua -lm -ldl")
 
all: c_app cpp_app
 
c_app: c_app.c
	$(CC) -o c_app c_app.c $(LUA_CFLAGS) $(LUA_LIBS)
 
cpp_app: cpp_app.cpp
	$(CXX) -std=c++17 -o cpp_app cpp_app.cpp $(LUA_CFLAGS) $(LUA_LIBS)
 
clean:
	rm -f c_app cpp_app

CMakeLists.txt 模板

cmake_minimum_required(VERSION 3.10)
project(LuaIntegration)
 
find_package(Lua REQUIRED)
 
add_executable(c_app c_app.c)
target_link_libraries(c_app ${LUA_LIBRARIES})
target_include_directories(c_app PRIVATE ${LUA_INCLUDE_DIR})
 
add_executable(cpp_app cpp_app.cpp)
target_link_libraries(cpp_app ${LUA_LIBRARIES})
target_include_directories(cpp_app PRIVATE ${LUA_INCLUDE_DIR})
set_target_properties(cpp_app PROPERTIES CXX_STANDARD 17)

下一步:05-Neovim示例.md — 使用 Lua 打造高效 Neovim 开发环境


相关知识点