C++与lua联合编程

一、环境配置

首先下载lua源码。

image-20240717211614791

将main函数改名后编译。

image-20240717211633975

目前我的工作目录是工程文件所在目录,src存放了lua的源码。

image-20240717212024743

修改dll输出路径。

image-20240717212140234

image-20240717213055702

指定导出宏生成.lib文件

生成 .lib 文件需要导出宏,这是为了确保在编译和链接过程中正确处理导入和导出的符号。具体来说,导出宏(export macro)用于标记哪些函数、变量或类应当从 DLL 中导出,使其可以在 DLL 外部被访问。

image-20240717213027504

image-20240717213302949

修改lib的输出路径。

image-20240717212303620

image-20240717213109132

二、lua基本语法

1.第一个lua和C++程序

image-20240717214858982

image-20240717215134442

ben

2.基本数据类型和变量

  • 全局变量

类型+变量名

image-20240717215941778

image-20240717215952423

image-20240717220005543

  • 本地变量(尽量用本地变量,保证及时的垃圾回收)

image-20240717220025102

image-20240717220104052

Lua基本数据类型:

2.1 Nil

在 Lua 中,nil 是一种特殊的数据类型,用于表示“无值”或“空值”。它的主要用途有以下几个方面:

  1. 表示变量没有值nil 用于区分变量是否有值。例如,如果一个变量被赋值为 nil,这意味着该变量目前没有任何值。
  2. 删除表中的元素:在 Lua 中,将表(table)中的元素赋值为 nil,可以删除该元素。
  3. 全局变量和垃圾回收:将全局变量设置为 nil 可以将其标记为可回收,从而允许垃圾回收器释放相关的内存。
local a = nil
print(type(a))  -- 输出:nil

这段代码展示了如何将一个局部变量 a 设为 nil,然后通过 type 函数检查其类型。type(a) 会返回 nil,表示变量 a 目前没有值。

2.2 Booleans

在 Lua 中,boolean 类型有两个值:truefalse。它们通常用于条件判断和控制流(如 if 语句、循环等)。

在 Lua 中,只有 falsenil 会被视为假(false),其他所有值,包括数值 0,都被视为真(true)。这与一些其他编程语言(如 C/C++)中的行为不同,在那些语言中,0 通常被视为假。

2.3 Numbers

  1. Lua 中没有整数,都是用浮点数运算

    在 Lua 5.3 之前,Lua 语言只使用浮点数来表示所有的数字,这意味着即使你写的是一个整数,内部也是用浮点数来存储和运算的。这种浮点数对应于 C 语言中的 double 类型。

  2. 新版 Lua 中有基于 64 位的整型

    从 Lua 5.3 开始,Lua 引入了整数类型(integer),这是一个 64 位的整数。这一变化使得 Lua 可以更高效地处理整数运算,同时也保留了对浮点数的支持。现在,Lua 支持两种数字类型:整数和浮点数。

  3. tonumber 转换格式

    tonumber 是 Lua 内置的一个函数,用于将字符串或其他类型的值转换为数字。这个函数在需要将其他数据类型转换为数字时非常有用。

image-20240717221752481

image-20240717221811534

2.4 String(最常用)

1.tostring 转换格式:tostring 函数可以将其他数据类型转换为字符串。

image-20240720123124555

2.多行字符串赋值:使用 [[]] 可以定义多行字符串,这在需要处理大段文本时非常有用。

image-20240720123258928

3.转义字符:Lua 中的字符串可以使用与 C 语言相同的转义字符。例如,\n 表示换行,\" 表示双引号。

image-20240720123417090

4.字符串拼接:Lua 使用 .. 运算符进行字符串拼接。

image-20240720123654579

3. 字符串处理

在Lua中,字符串处理是一个非常常见的任务,Lua提供了一些内置函数来处理字符串。

3.1 错误处理

image-20240720124238631

3.2 字符串长度:string.len

string.len 函数用于获取字符串的长度。

image-20240720124523504

image-20240720124728580

加载string库

在 Lua 5.2 及以后的版本中,luaL_openlibs 函数会自动打开所有标准库。

image-20240720130810760

3.3 字符串子串 :string.sub

string.sub 函数用于从字符串中提取子串。参数包括字符串、起始位置和结束位置。

image-20240720131817404

3.4 字符串查找: string.find

string.find 函数用于在字符串中查找子串,返回子串的起始和结束位置。它支持正则表达式。

image-20240720131656977

3.5字符串替换: string.gsub

string.gsub 函数用于在字符串中替换子串。它支持正则表达式。

image-20240720131933396

4.控制结构语句

4.1 if条件语句

条件语句结构:

if 条件 then
    -- then-part
elseif 其他条件 then
    -- elseif-part
else
    -- else-part
end

在条件语句中,可以使用逻辑操作符来构建更复杂的条件表达式。常见的逻辑操作符包括:

  • < :小于
  • > :大于
  • <= :小于等于
  • >= :大于等于
  • ~= :不等于
  • == :等于

image-20240720222905809

image-20240720222928486

4.2 while 循环语句

while 循环语句用于在条件为真时重复执行某段代码。当条件变为假时,循环结束。while 循环的基本结构如下:

while 条件 do
    -- 循环体
end

在循环中,可以使用 break 语句提前退出循环。

在 Lua 中,not 操作符用于取反一个条件表达式。在使用 not 操作符时,注意加上括号以确保逻辑的正确性。

image-20240720230007415

4.3 repeat循环语句

repeat...until 循环类似于 while 循环,但它至少会执行一次循环体,然后再检查条件是否为真。如果条件为假,循环体会继续执行,直到条件为真时退出循环

repeat
    -- 循环体
until 条件

image-20240720230458003

image-20240720230633261

4.4 for循环语句

Lua 提供了两种类型的 for 循环:数值循环和泛型循环。

数值循环用于遍历一段数值范围,具有固定的步长。

for var = from, to, step do
    -- 循环体
end

image-20240720230903497

image-20240720230933083

泛型循环用于遍历集合,如表(数组)或字典。Lua 提供了 pairsipairs 函数来支持泛型循环。

  • pairs 遍历表的所有键值对,适用于字典。

image-20240720232014144

image-20240720232219227

  • ipairs 以整数顺序遍历表的元素,适用于数组。

image-20240720231246550

5.表和函数

5.1表的大小

table.getn(t) 函数用于获取表 t 的大小,但在 Lua 5.1 之后的版本中,建议使用 # 操作符。

在 Lua 中,# 操作符(长度运算符)只能用于顺序整数键的表(即数组),而不能用于键为字符串或非连续整数的表(即字典)。

image-20240721004631723

image-20240721004710470

5.2 插入元素

table.insert(t, pos, value) 函数用于在表 t 中插入一个元素。如果没有指定 pos,则默认在表的末尾插入。

image-20240721005627015

字典的元素插入和删除

image-20240721005339310

5.3 删除元素

table.remove(t, [pos]) 函数用于从表 t 中删除一个元素。如果没有指定 pos,则默认删除表的最后一个元素。函数返回被删除的元素。

image-20240721005849522

5.4 二维数组

image-20240721011511994

5.5 函数

function func_name(arguments-list)
    -- statements-list
end

Lua 函数可以接受普通参数和可变参数。

普通参数

image-20240721011835977

可变参数

image-20240721012146775

image-20240721012305320

image-20240721012532723

返回值

image-20240721013146582

使用变量定义函数

image-20240721013333040

三、Lua调用C++

image-20240721013447292

image-20240721013535530

1.原理

Lua 调用 C++ 函数的基本原理是将 C++ 函数注册到 Lua 虚拟机中,使其可以在 Lua 脚本中像普通 Lua 函数一样调用。这涉及以下几个步骤:

  1. 定义C++函数:首先,我们定义一个C++函数,例如 addgreet。这些函数的参数类型都是 lua_State*,并且返回值类型是 int
  2. 获取参数:使用 lua_tonumberlua_tostring 等函数从Lua栈中获取参数。
  3. 执行逻辑:在C++函数中执行所需的逻辑操作。
  4. 返回结果:将结果压入Lua栈,并返回结果数量。
  5. 注册函数:使用 lua_register 将C++函数注册为Lua全局函数。
  6. 调用函数:在Lua脚本中,直接调用注册的C++函数

返回值数量:函数最后返回一个整数,表示压入Lua栈的返回值数量。

image-20240721015839563

image-20240721015814504

2.传递参数类型

Lua 和 C++ 之间可以传递多种类型的参数,包括数字、字符串、布尔值和用户自定义类型(如指针或结构体)。

  • lua_gettop(lua_State* L):返回堆栈中元素的数量,即传递给函数的参数数量。
  • lua_isnumber(lua_State* L, int index):检查堆栈中的值是否是数字。
  • lua_tonumber(lua_State* L, int index):将堆栈中的值转换为数字。
  • lua_isstring(lua_State* L, int index):检查堆栈中的值是否是字符串。
  • lua_tostring(lua_State* L, int index):将堆栈中的值转换为字符串。
  • lua_pushnumber(lua_State* L, lua_Number n):将一个数字压入堆栈。
  • lua_pushstring(lua_State* L, const char* s):将一个字符串压入堆栈。

在 Lua 中,参数的位置是从 1 开始索引的。第一个参数的位置是 1,第二个参数的位置是 2,以此类推。通过在 C++ 函数中使用 lua_tonumberlua_tostring 等函数,并传入相应的索引,可以获取相应的参数值。

2.1 传递普通参数

image-20240721021057165

image-20240721021105166

image-20240721021925453

2.2 传递数组参数

image-20240721013535530

image-20240721022450816

lua_gettable 使用栈顶的索引(即 i)从表中获取对应的值,并将该值压入栈顶。例如,如果 i1,获取数组中第一个元素,并将该元素压入栈顶。

image-20240721024335417

在Lua中,所有的操作都是通过堆栈完成的。当你希望从表中获取某个元素时,首先需要将该元素的索引(下标)压入堆栈。

lua_pushnumber(L, i);  // 将索引 i 压入栈顶

这行代码将当前的索引 i 压入堆栈。lua_pushnumber 函数将一个数字压入堆栈。

在将索引压入堆栈之后,使用 lua_gettable 函数来获取表中的值。lua_gettable 会使用栈顶的值作为索引,从给定位置的表中获取相应的值,并将该值压入栈顶。

lua_gettable(L, 1);  // 从索引为 1 的表中获取值(根据栈顶的索引 i)

在处理完当前元素后,需要将栈顶的值弹出,以便在下一次迭代时堆栈状态保持一致。

lua_pop(L, 1);  // 弹出栈顶的值

2.3 传递表

2.4 参数类型检查

3.获取返回值类型

C++ 函数可以返回各种类型的值给 Lua 脚本,包括数字、字符串、布尔值和结构体对象。Lua 脚本可以通过 Lua API 获取这些返回值并使用它们。

四、C++调用Lua

1.C++给Lua传递变量并访问Lua的全局变量

2.C++给Lua传递表并访问Lua的表

3.C++调用Lua的函数

4.错误显示和堆栈清理

5.C++调用Lua的函数并传递参数

6.C++调用Lua函数并获取返回的表

为 1 的表中获取值(根据栈顶的索引 i)

在处理完当前元素后,需要将栈顶的值弹出,以便在下一次迭代时堆栈状态保持一致。

lua_pop(L, 1);  // 弹出栈顶的值

2.3 传递表

2.4 参数类型检查

3.获取返回值类型

C++ 函数可以返回各种类型的值给 Lua 脚本,包括数字、字符串、布尔值和结构体对象。Lua 脚本可以通过 Lua API 获取这些返回值并使用它们。

四、C++调用Lua

1.C++给Lua传递变量并访问Lua的全局变量

2.C++给Lua传递表并访问Lua的表

3.C++调用Lua的函数

4.错误显示和堆栈清理

5.C++调用Lua的函数并传递参数

6.C++调用Lua函数并获取返回的表

五、Lua和MFC结合开发

相关推荐

  1. pythonc#联合编程简单案例

    2024-07-22 08:48:01       45 阅读
  2. Lua编译运行

    2024-07-22 08:48:01       46 阅读
  3. Lua-LuaC++的交互2

    2024-07-22 08:48:01       31 阅读
  4. Lua-LuaC的交互3

    2024-07-22 08:48:01       34 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-22 08:48:01       52 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-22 08:48:01       54 阅读
  3. 在Django里面运行非项目文件

    2024-07-22 08:48:01       45 阅读
  4. Python语言-面向对象

    2024-07-22 08:48:01       55 阅读

热门阅读

  1. 深度学习简介(框架)

    2024-07-22 08:48:01       16 阅读
  2. ChatGPT的工作记忆容量:一项实证研究

    2024-07-22 08:48:01       14 阅读
  3. AI学习指南机器学习篇-SOM的拓扑结构与参数调优

    2024-07-22 08:48:01       17 阅读
  4. 如何调整图像的窗宽窗位

    2024-07-22 08:48:01       16 阅读
  5. linux字符设备驱动+fops应用测试程序

    2024-07-22 08:48:01       15 阅读
  6. opencv—常用函数学习_“干货“_14

    2024-07-22 08:48:01       17 阅读
  7. 网络安全防线:黑龙江等级保护测评标准详解

    2024-07-22 08:48:01       17 阅读
  8. thinkphp8结合layui2.9 图片上传验证

    2024-07-22 08:48:01       15 阅读
  9. grub之loongarch架构调试

    2024-07-22 08:48:01       13 阅读
  10. 任务3 git基础知识(主要是pr的笔记)

    2024-07-22 08:48:01       18 阅读
  11. CUDA 在机器学习中的应用 - 直观而全面的解释

    2024-07-22 08:48:01       18 阅读
  12. ChatGPT:Spring Boot 怎么配置上下文路径?

    2024-07-22 08:48:01       16 阅读
  13. springboot项目中,项目打包时,跳过Test类

    2024-07-22 08:48:01       18 阅读