一.配置Lua C++交互环境

1.下载Lua 包环境

  地址: https://www.lua.org/download.html ,我们这里用的是5.4.2版本。

  2.新建C++ 控制台应用程序

 3.导入Lua 源码

  1)导入Lua 源码到同级目录(这样做为了Main函数所在类添加Lua 的C 类的时候直接可以include,不需要考虑目录层级问题)

  

  打开的目录里,将5.4.2 的lua包里的 src目录里的文件全部拷到此目录

  2)添加Lua 源码

  

  选中刚刚导入的Lua文件

  3)编译

  这时,点击目录生成,回发现报错

这是关键报错信息,重复main头文件,众所周知,main函数是启动函数;那就注释调main.

会发现,有两处main ,lua.c 中 int main 和luac.c int main,分别都注释了。(或者简单粗暴,直接将luc.c和luac.c直接删除也可以)

再点生成,成功。这两处main,其实就是如果你将此lua编码打包成exe,就是启动函数。但是我们这里不需要这边的main,我们自己新建的C++ 应用程序,是有自己的Main。

二.Hello.lua 运行

  新建Lua脚本,必须.lua 结尾。

 1.关键API

  1)lua与C++交互,必须要一个虚拟栈。可通过lua_State* L = luaL_newstate(); 对于栈的介绍可参考:https://blog.csdn.net/shun_fzll/article/details/39120965,这里就不对栈作描述了。

  2)加载Lua文件,可通过 luaL_dofile 返回一个 int类型,返回结果不为0,则表示异常

  3)Lua有异常,会把返回结果返回到栈顶,也就是说报异常了,可以通过lua_tostring(L,-1)得到报啥错,再打印出来.

  4)lua_close 就是释放这个栈。

  5)对于C++调用 C的头文件,需要extern

 2.实例分析

 1 #include <iostream>
2 #include <string.h>
3 using namespace std;
4 extern "C"
5 {
6 #include "lua.h"
7 #include "lualib.h"
8 #include "lauxlib.h"
9 }
10 int main()
11 {
12 std::cout << "Hello World!\n";
13 lua_State* L = luaL_newstate();
14 int Ret = luaL_dofile(L, "LuaHello.lua");
15 if (Ret)
16 {
17 string strError = lua_tostring(L, -1);
18 cout << strError.c_str() << endl;
19 return -1;
20 }
21
22 lua_close(L);
23 return 0;
24 }

  1)运行上述代码

  2)想一下,好像lua代码是运行了,但是print怎么会nil,并报错,提示的还挺智能,具体行号都报出来了。

我们再试着修改Lua代码中下移两行试试:

  3)咦,那就证明Lua文件是肯定运行了,就是异常了。找不到print,print不是lua库里的函数嘛,为啥拿不到了。

因为C++环境中创建Lua_State这个栈,这个默认并没有打开lua标准库。所以查一下。

在 上述Line:13 后面新增 luaL_openlibs(L);

  运行 得到 

  恭喜,C++ 与Lua通信成功。

三.Lua UserData应用实例

  关于具体lua与C交互的一些常见操作,可参考:https://blog.csdn.net/shun_fzll/article/details/39120965

  

  问题:有时候,你会想,我在C++中声明了一个struct,在lua中,也想声明这个struct,怎么弄纳?接下来这个案例就是教你如何使。

我们的UserData就是解决这个问题的。

  Lua UserData分两种,我们这说的是FullUserData,就是可以解决上述问题的UserData.

  直奔主题,看代码分析。

  Lua5.1之前和之后的注册函数差距很大,详情可参考:https://blog.csdn.net/ljhjason/article/details/28860633

  Lua5.1之后可以使用 luaL_requiref 代替 Lua5.1之前的luaL_register ,可参考:https://blog.csdn.net/ljhjason/article/details/28860633

  

 1 #include <iostream>
2 #include <string.h>
3 using namespace std;
4 extern "C"
5 {
6 #include "lua.h"
7 #include "lualib.h"
8 #include "lauxlib.h"
9 }
10
11 struct TestCStruct
12 {
13 char* Name;
14 int Num = 1;
15 };
16
17 int NewTestCStruct(lua_State* L)
18 {
19 size_t iBytes = sizeof(struct TestCStruct);
20 struct TestCStruct* pStruct = (struct TestCStruct*)lua_newuserdata(L, iBytes);
21 return 1;
22 }
23
24 int SetNum(lua_State* L)
25 {
26 struct TestCStruct *pStruct = (struct TestCStruct*)lua_touserdata(L, 1);
27 luaL_argcheck(L, pStruct != NULL, 1, "Error Param");
28 int num = luaL_checkinteger(L, 2);
29 luaL_argcheck(L, num > 0, 2,"Wrong Paramter");
30 pStruct->Num = num;
31 return 1;
32 }
33
34 int GetNum(lua_State* L)
35 {
36 struct TestCStruct *pStruct = (struct TestCStruct*)lua_touserdata(L, 1);
37 luaL_argcheck(L, pStruct != NULL, 1, "ErrorStruct");
38 lua_pushinteger(L, pStruct->Num);
39 return 1;
40 }
41
42 struct luaL_Reg arrayFunc[] = {
43 {"new",NewTestCStruct},
44 {"SetNum",SetNum},
45 {"SNum",GetNum},
46 {NULL,NULL}
47 };
48
49 LUALIB_API int luaopen_mytest(lua_State* L)
50 {
51 luaL_newlib(L, arrayFunc);
52 return 1;
53 }
54
55 int main()
56 {
57 std::cout << "Hello World!\n";
58 lua_State* L = luaL_newstate();
59 luaL_openlibs(L);
60 luaL_requiref(L, "mytest", luaopen_mytest, 0);
61 int Ret = luaL_dofile(L, "LuaHello.lua");
62 if (Ret)
63 {
64 string strError = lua_tostring(L, -1);
65 cout << strError.c_str() << endl;
66 return -1;
67 }
68
69 lua_close(L);
70 return 0;
71 }

Lua中源码

local t = require("mytest")
print("t:" .. tostring(t)) local y = t.new()
print("y :" .. tostring(y))
t.SetNum(y,100)
print("Num:" ..t.SNum(y))
local y2 = t.new()
print("y2 :" .. tostring(y2))
print("Hello lua and C++")

运行结果

综上, 可以看到Full UserData 的使用,主要核心是Line:60 luaL_requiref的使用。

最新文章

  1. .NET 获取客户端的操作系统版本、浏览器版本和IP地址
  2. SPSS数据分析—两阶段最小二乘法
  3. js中java式的类成员
  4. iOS开发——UI进阶篇(三)自定义不等高cell,如何拿到cell的行高,自动计算cell高度,(有配图,无配图)微博案例
  5. 用于软件包管理的21个Linux YUM命令 转载
  6. php文件和目录操作函数
  7. Oracle超出最大连接数问题及解决
  8. SoundPool没有声音的问题
  9. [置顶] 【SQL】查询重复人名的次数并列出
  10. EBS查找运行请求时间,参数等
  11. stl的集合set——安迪的第一个字典(摘)
  12. Ueditor和CKeditor 两款编辑器的使用与配置
  13. CPU指令的流水线运行
  14. Delphi的字符(Char),字符串(String),字符串指针(PChar),字符数组arrayofchar(来自http://delphi.cjcsoft.net/论坛)
  15. QT 打开文件对话框汇总
  16. UVa 10551 - Basic Remains
  17. Eclipse 版本选择
  18. toolbar ,textfield,图片拉伸,Bundle
  19. JavaScript 中 this 的详解
  20. 数据库MySQL——初识

热门文章

  1. P2762 太空飞行计划问题 (最小割)
  2. 【noi 2.6_8787】数的划分(DP){附【转】整数划分的解题方法}
  3. c++派生类中构造函数和析构函数执行顺序、判断对象类型、抽象类、虚函数
  4. JS编程练习:将目标节点内部的子节点逆序
  5. 深入剖析JavaScript中的对象与原始值之间的转换机制
  6. 高并发之Semaphore、Exchanger、LockSupport
  7. php foundation knowledge!
  8. Sass &amp;&amp; SCSS &amp;&amp; Less
  9. Swift 5.3
  10. bob and brad physical therapy knee exercise