现代 C++/Lua 绑定库
sol2 是一个现代、轻量、高性能的 C++17/20 头文件库,用于在 C++ 和 Lua 之间进行无缝交互。它是 sol(Simple Object Lua)库的现代版本,提供了更简洁、更安全、更高效的 API。
// 下载 sol.hpp 并直接包含
#include "sol.hpp"
vcpkg install sol2
conan install sol2/3.3.0@
#include <iostream>
#include "sol.hpp"
int main() {
// 创建 Lua 状态
sol::state lua;
// 执行 Lua 代码
lua.script("print('Hello from Lua!')");
// 从 C++ 调用 Lua 函数
lua.script("function greet(name) return 'Hello, ' .. name .. '!' end");
std::string greeting = lua["greet"]("World");
std::cout << greeting << std::endl;
return 0;
}
sol::state lua;
// 设置全局变量
lua["x"] = 24;
lua["y"] = 16;
lua["message"] = "Hello from C++";
// 执行 Lua 代码
lua.script(R"(
print(x + y)
print(message)
print(x * y)
)");
// C++ 函数
int add(int a, int b) {
return a + b;
}
std::string greet(const std::string& name) {
return "Hello, " + name + "!";
}
void print_vector(const std::vector<int>& v) {
for (int x : v) {
std::cout << x << " ";
}
std::cout << std::endl;
}
int main() {
sol::state lua;
// 注册 C++ 函数到 Lua
lua["add"] = add;
lua["greet"] = greet;
lua["print_vector"] = print_vector;
// 在 Lua 中调用
lua.script(R"(
print(add(5, 3))
print(greet("Lua"))
print_vector({1, 2, 3, 4, 5})
)");
return 0;
}
sol::state lua;
// 创建表
sol::table config = lua.create_table();
config["width"] = 1920;
config["height"] = 1080;
config["fullscreen"] = true;
// 创建嵌套表
config["display"] = lua.create_table_with(
"brightness", 0.8,
"contrast", 1.2
);
// 在 Lua 中访问
lua.script(R"(
print(config.width)
print(config.height)
print(config.display.brightness)
)");
lua.script(R"(
player = {
name = "John",
level = 25,
inventory = {"sword", "shield", "potion"}
}
)");
// 获取表
sol::table player = lua["player"];
std::string name = player["name"];
int level = player["level"];
// 获取数组
std::vector<std::string> inventory = player["inventory"];
std::cout << "Name: " << name << ", Level: " << level << std::endl;
for (const auto& item : inventory) {
std::cout << "Item: " << item << std::endl;
}
#include <iostream>
#include <string>
#include "sol.hpp"
// C++ 类
class Player {
private:
std::string name_;
int health_;
public:
Player(const std::string& name, int health)
: name_(name), health_(health) {}
void attack(int damage) {
std::cout << name_ << " attacks for " << damage << " damage!" << std::endl;
}
void heal(int amount) {
health_ += amount;
std::cout << name_ << " heals for " << amount << " HP!" << std::endl;
}
std::string getName() const { return name_; }
int getHealth() const { return health_; }
};
int main() {
sol::state lua;
// 绑定类到 Lua
lua.new_usertype<Player>("Player",
// 构造函数
sol::constructors<Player(const std::string&, int)>(),
// 属性
"name", &Player::getName,
"health", &Player::getHealth,
// 方法
"attack", &Player::attack,
"heal", &Player::heal
);
// 在 Lua 中使用
lua.script(R"(
local player = Player.new("Hero", 100)
print(player.name)
print("Health:", player.health)
player:attack(25)
player:heal(10)
)");
return 0;
}
// 加载配置文件
lua.script_file("config.lua");
// 读取配置
std::string server = lua["config"]["server"];
int port = lua["config"]["port"];
bool debug = lua["config"]["debug"];
std::cout << "Server: " << server << ":" << port << std::endl;
std::cout << "Debug: " << (debug ? "on" : "off") << std::endl;
/*
-- config.lua 内容
config = {
server = "localhost",
port = 8080,
debug = true,
log_file = "app.log"
}
*/
lua.script_file("game_logic.lua");
// 脚本中定义的函数
auto initGame = lua["initGame"];
auto updateGame = lua["updateGame"];
auto processInput = lua["processInput"];
// 调用 Lua 函数
initGame();
updateGame(0.016f); // delta time
processInput("W", "up");
/*
-- game_logic.lua 内容
function initGame()
print("Game initialized!")
end
function updateGame(dt)
print("Update: " .. dt)
end
function processInput(key, action)
print("Key: " .. key .. ", Action: " .. action)
end
*/
sol::state lua;
// 捕获 Lua 错误
try {
lua.script("this is invalid lua code");
} catch (sol::error& e) {
std::cerr << "Lua 错误: " << e.what() << std::endl;
}
// 安全执行
auto result = lua.safe_script("return 1 + 1");
if (result.valid()) {
std::cout << "结果: " << result.get<int>() << std::endl;
} else {
sol::error err = result;
std::cerr << "执行失败: " << err.what() << std::endl;
}