C++ 与 lua 联合编程

9/2/2024 luaC++

# 环境部署

有两种方案

# 全局安装 lua 解释器

brew install lua
1

使用 pkg-config 在 cmake 中载入 lua

find_package(PkgConfig REQUIRED)
pkg_check_modules(LUA REQUIRED lua)
target_link_libraries(main PRIVATE ${LUA_LIBRARIES})
target_link_directories(main PRIVATE ${LUA_LIBRARY_DIRS})
target_include_directories(main PRIVATE ${LUA_INCLUDE_DIRS})
1
2
3
4
5

# vcpkg

{
    "name":             "cxx-lua",
    "version-string":   "1.0.0",
    "builtin-baseline": "e590c2b30c08caf1dd8d612ec602a003f9784b7d",
    "dependencies":     [
        {
            "name":      "lua",
            "version>=": "5.4.6"
        }
    ]
}
1
2
3
4
5
6
7
8
9
10
11

在 cmake 中载入 lua

find_package(Lua REQUIRED)
target_include_directories(main PRIVATE ${LUA_INCLUDE_DIR})
target_link_libraries(main PRIVATE ${LUA_LIBRARIES})
1
2
3

vcpkg 也支持全局模式,与 brew 用法区别不大不再赘述

# Hello World

为了避免函数名冲突,要使用 extern "C" 包裹lua头文件,声明这些是C的函数。 lua 是脚本语言,修改 lua 文件之后无需重新编译 C++,重新执行程序即可

main.lua

print "Hello World"
1

main.cpp

#include <iostream>

// 避免函数签名冲突
extern "C" {
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
}

int main() {
    lua_State* L = luaL_newstate(); // 5.0 之后使用 luaL_newstate 替代 lua_open
    if (!L) {
        std::cerr << "Cannot create state: Not enough memory" << std::endl;
        return 1;
    }

    luaL_openlibs(L);

    if (luaL_loadfile(L, "main.lua")) {
        std::cerr << "lua load error: " << lua_tostring(L, -1) << std::endl;
    }

    if (lua_pcall(L, 0, 0, 0)) {
        std::cerr << "lua call error: " << lua_tostring(L, -1) << std::endl;
    }

    lua_close(L);
    return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

执行结果

Hello World
1

# 变量

全局变量,全局可用

a = 100
1

本地变量,从当前作用域离开之后就会被垃圾回收,类似 RAII

local a = 100 
1

# 数据类型

四个基础数据类型

  • Nil
  • Booleans
  • Numbers
  • Strings

Booleans 和 Nil 不赘述

# 识别变量类型

i = 100
s = "str"
print(type(i), type(s))
1
2
3

运行结果

number  string
1

# Numbers

在 lua 5.1 之后 int 类型基于双精度类型存储

a = 100
1

# Strings

a = "string"
1

多行字符串使用 [[]] 定义

s = [[
<html>
    <h1>Hello World
    </h1>
</html>
]]

print(s)
1
2
3
4
5
6
7
8

拼接字符串使用 .. 运算符,同时也可以拼接数字类型

a = "lua".."str"..123
1

一部分标准库

  • 获取长度 string.len(a)
  • 截取 string.sub(a, 2, 3)
  • 查找 local b, c = string.find(a, "HEAD or regex")
  • 替换 string.gsub(a, "str or regex", "new str")

# 类型转换

i = 100
s = "1"

print(type(i), type(s))
print(type(tostring(i)), type(tonumber(s)))
1
2
3
4
5

运行结果

number  string
string  number
1
2

# 数组

#

# 在 lua 中引用其他 lua 文件

dofile("do.lua")
1

示例程序

main.lua

a = 100
local b = 1

print("print a in main.lua", a)
print("print b in main.lua", b)

dofile("sub.lua")
1
2
3
4
5
6
7

sub.lua

print("print a in sub.lua", a)
print("print b in sub.lua", b)
1
2

执行结果

全局变量可以跨文件读取,但局部变量不能

print a in main.lua     100
print b in main.lua     1
print a in sub.lua      100
print b in sub.lua      nil
1
2
3
4

# 流程控制

# 分支

分支采用 if then end 结构,elseif 也要加 then

a = 2;

if (a == 1 or a == 2) then
	print(12, a)
elseif (a == 3) then
	print(3, a)
else
	print(0, a)
end
1
2
3
4
5
6
7
8
9

# 循环

while

a = 0;

while (a < 5) do
    print(a)
    a = a + 1
end
1
2
3
4
5
6

运行结果

0
1
2
3
4
1
2
3
4
5

# repeat

repeat .. until 类似 do .. while

a = 0;

repeat
    print(a)
    a = a + 1
until a > 5
1
2
3
4
5
6

# for

for 
1

# 泛型

Last Updated: 8/19/2024, 5:33:26 AM