1. //这是一篇lua与C++交互的情景测试
  1. #include <lua.hpp>
  2. #include <lauxlib.h>
  3. #include <lualib.h>
  4. #include <string.h>
  5. #include <limits.h>
  6.  
  7. #pragma region not_importent_
  8. static void stackDump (lua_State *L)
  9. {
  10. int i;
  11. int top = lua_gettop(L);
  12. for(i=1;i<=top;i++){
  13. /*repeatforeachlevel*/
  14. int t = lua_type(L, i);
  15. switch (t) {
  16. case LUA_TSTRING:
  17. /* strings */
  18. printf("`%s'", lua_tostring(L, i));
  19. break;
  20. case LUA_TBOOLEAN:
  21. /* booleans */
  22. printf(lua_toboolean(L, i) ? "true" : "false");
  23. break;
  24. case LUA_TNUMBER:
  25. /* numbers */
  26. printf("%g", lua_tonumber(L, i));
  27. break;
  28. default:
  29. /* other values */
  30. printf("%s", lua_typename(L, t));
  31. break;
  32. }
  33. printf(" ");
  34. /* put a separator */
  35. }
  36. printf("\n");
  37. /* end the listing */
  38. }
  39.  
  40. void error (lua_State *L, const char *fmt, const char *str) {
  41. printf(fmt, str);
  42. }
  43. //待Lua调用的C注册函数。
  44. static int add2(lua_State* L)
  45. {
  46. //检查栈中的参数是否合法,1表示Lua调用时的第一个参数(从左到右),依此类推。
  47. //如果Lua代码在调用时传递的参数不为number,该函数将报错并终止程序的执行。
  48. double op1 = luaL_checknumber(L,1);
  49. double op2 = luaL_checknumber(L,2);
  50. //将函数的结果压入栈中。如果有多个返回值,可以在这里多次压入栈中。
  51. lua_pushnumber(L,op1 + op2);
  52. //返回值用于提示该C函数的返回值数量,即压入栈中的返回值数量。
  53. return 1;
  54. }
  55. static int sub2(lua_State* L)
  56. {
  57. double op1 = luaL_checknumber(L,1);
  58. double op2 = luaL_checknumber(L,2);
  59. lua_pushnumber(L,op1 - op2);
  60. return 1;
  61. }
  62. #pragma endregion
  63.  
  64. //////////////////////////////////////////////////////////////////////////
  65. void test_c_call_lua_fun_noParam()
  66. {
  67. const char* buff = "print(\"hello\")";
  68. int err;
  69.  
  70. //init
  71. lua_State* L = luaL_newstate();
  72. luaL_openlibs(L);
  73.  
  74. //load buff
  75. err = luaL_loadbuffer(L,buff,strlen(buff),"line") ;
  76. err += lua_pcall(L,0,0,0);
  77. int s = lua_gettop(L);
  78. if(err){
  79. fprintf(stderr,"%s",lua_tostring(L,-1));
  80. lua_pop(L,1);
  81. }
  82.  
  83. //close
  84. lua_close(L);
  85.  
  86. }
  87. //////////////////////////////////////////////////////////////////////////
  88. void test_c_call_lua_fun_withParam()
  89. {
  90. lua_State *L = luaL_newstate();
  91. luaL_openlibs(L);
  92. if (luaL_loadfile(L, "luafile2.lua") || lua_pcall(L, 0, 0, 0))
  93. {
  94. error(L, "cannot run configuration file: %s",lua_tostring(L, -1));
  95. return;
  96. }
  97. lua_getglobal(L, "do_lua_kk");
  98. lua_getglobal(L, "a");
  99. lua_getglobal(L, "do_lua_error");
  100. lua_getglobal(L, "b");
  101. lua_getglobal(L, "do_c_one");
  102. lua_getglobal(L, "do_c");
  103. lua_getglobal(L, "width");
  104. lua_getglobal(L, "height");
  105. // lua_getglobal(L, "do_c_two");
  106. stackDump(L); //打印结果:function `lua_str_a' function `lua_str_b' function function 999 300
  107. int k = 100;
  108.  
  109. k = lua_pcall(L, 2, 1, 1);
  110. stackDump(L); //打印结果:function `lua_str_a' function `lua_str_b' function 8888
  111. /*lua 执行栈上最上面的函数,使用栈上2个参数,向栈压入3个返回值
  112. 使用栈上第1位置的函数do_lua_kk作为错误处理回调函数,输出:
  113. -------->do_c
  114. 999--add--300-->--2222
  115. */
  116. k = lua_pcall(L, 1, 0, 0);
  117. stackDump(L);
  118.  
  119. lua_close(L);
  120. }
  121. //////////////////////////////////////////////////////////////////////////
  122. void test_c_call_lua_fun_withParam2()
  123. {
  124. lua_State* L = luaL_newstate();
  125.  
  126. //luaL_dostring 等同于luaL_loadstring() || lua_pcall()
  127. //注意:在能够调用Lua函数之前必须执行Lua脚本,否则在后面实际调用Lua函数时会报错,
  128. //错误信息为:"attempt to call a nil value."
  129. const char* lua_function_code = "function add(x,y) return x + y end";
  130. if (luaL_dostring(L,lua_function_code)) {
  131. printf("Failed to run lua code.\n");
  132. return;
  133. }
  134. double x = 1.0, y = 2.3;
  135. lua_getglobal(L,"add");
  136. lua_pushnumber(L,x);
  137. lua_pushnumber(L,y);
  138. //下面的第二个参数表示带调用的lua函数存在两个参数。
  139. //第三个参数表示即使带调用的函数存在多个返回值,那么也只有一个在执行后会被压入栈中。
  140. //lua_pcall调用后,虚拟栈中的函数参数和函数名均被弹出。
  141. if (lua_pcall(L,2,1,0)) {
  142. printf("error is %s.\n",lua_tostring(L,-1));
  143. return;
  144. }
  145. //此时结果已经被压入栈中。
  146. if (!lua_isnumber(L,-1)) {
  147. printf("function 'add' must return a number.\n");
  148. return;
  149. }
  150. double ret = lua_tonumber(L,-1);
  151. lua_pop(L,-1); //弹出返回值。
  152. printf("The result of call function is %f.\n",ret);
  153. lua_close(L);
  154.  
  155. }
  156. //////////////////////////////////////////////////////////////////////////
  157. void test_c_use_lua_variant()
  158. {
  159. const char* luascript = "width=111 ; height=222";
  160. lua_State* L = luaL_newstate();
  161. int w,h;
  162. //luaL_loadfile的作用是编译lua文件为一个chunk
  163. //把这个chunk当作一个匿名函数压在栈上
  164. //lua_pcall的作用是执行这个匿名函数,然后才能取得栈上的值
  165. if(luaL_loadstring(L,luascript) || lua_pcall(L,0,0,0)){
  166. printf("Error msg is %s.\n",lua_tostring(L,-1));
  167. return;
  168. }
  169. lua_getglobal(L,"width"); //调用次函数,则把全局变量压栈
  170. lua_getglobal(L,"height");//这里压栈次序决定了后面取值的索引
  171. if(!lua_isnumber(L,-2)){
  172. printf("width must be number\n");
  173. return;
  174. }
  175. if(!lua_isnumber(L,-1)){
  176. printf("height must be number\n");
  177. return ;
  178. }
  179. w = lua_tointeger(L,-2);
  180. h = lua_tointeger(L,-1);
  181.  
  182. printf("width = %d height = %d\n",w,h);
  183. lua_close(L);
  184. }
  185. //////////////////////////////////////////////////////////////////////////
  186. void test_c_use_lua_table()
  187. {
  188. lua_State* L = luaL_newstate();
  189. if (luaL_loadstring(L,"background = { r = 0.30, g = 0.10, b = 0 }")
  190. || lua_pcall(L,0,0,0)) {
  191. printf("Error Msg is %s.\n",lua_tostring(L,-1));
  192. return;
  193. }
  194. lua_getglobal(L,"background");
  195. if (!lua_istable(L,-1)) {
  196. printf("'background' is not a table.\n" );
  197. return;
  198. }
  199. //下面取栈上的table内容
  200. lua_getfield(L,-1,"r");
  201. if (!lua_isnumber(L,-1)) {
  202. printf("Invalid component in background color.\n");
  203. return;
  204. }
  205. int r = (int)(lua_tonumber(L,-1) * 255);
  206. lua_pop(L,1);//出栈
  207.  
  208. lua_getfield(L,-1,"g");
  209. if (!lua_isnumber(L,-1)) {
  210. printf("Invalid component in background color.\n");
  211. return;
  212. }
  213. int g = (int)(lua_tonumber(L,-1) * 255);
  214. lua_pop(L,1);
  215.  
  216. lua_pushnumber(L,0.4);//入栈,栈顶位置-1的值是0.4
  217. lua_setfield(L,-2,"b");//设置background["b"]=0.4,注意-2这个位置表示table的位置!!
  218. lua_getfield(L,-1,"b");//取table值
  219. stackDump(L);
  220. if (!lua_isnumber(L,-1)) {
  221. printf("Invalid component in background color.\n");
  222. return;
  223. }
  224. int b = (int)(lua_tonumber(L,-1) * 255);
  225. printf("r = %d, g = %d, b = %d\n",r,g,b);
  226. lua_pop(L,1);
  227. stackDump(L);
  228. lua_pop(L,1); //栈被清空了
  229.  
  230. lua_close(L);
  231. }
  232. //////////////////////////////////////////////////////////////////////////
  233. void test_c_new_lua_table()
  234. {
  235. lua_State* L = luaL_newstate();
  236. lua_newtable(L);//Lua会生成一个新的table对象并将其压入栈中。
  237. lua_pushnumber(L,0.3);
  238. stackDump(L);//table 0.3
  239. lua_setfield(L,-2,"r");//设置table["r"]=0.3完了把0.3弹出
  240. stackDump(L);//table
  241.  
  242. lua_pushnumber(L,0.1);
  243. lua_setfield(L,-2,"g");
  244.  
  245. lua_pushnumber(L,0.4);
  246. lua_setfield(L,-2,"b");
  247.  
  248. stackDump(L);//table
  249. lua_setglobal(L,"background");//栈顶元素出栈
  250. stackDump(L);//nil
  251. //调用该宏后,Lua会将当前栈顶的值赋值给第二个参数指定的全局变量名。
  252. //该宏在执行成功后,会将刚刚赋值的值从栈顶弹出。
  253.  
  254. lua_getglobal(L,"background");//把background压栈
  255. stackDump(L);//table
  256. if (!lua_istable(L,-1)) {
  257. printf("'background' is not a table.\n" );
  258. return;
  259. }
  260. lua_getfield(L,-1,"r");//table["r"]压栈
  261. stackDump(L);//table 0.3
  262. if (!lua_isnumber(L,-1)) {
  263. printf("Invalid component in background color.\n");
  264. return;
  265. }
  266. int r = (int)(lua_tonumber(L,-1) * 255);
  267. lua_pop(L,1);//table
  268.  
  269. lua_getfield(L,-1,"g");//table 0.1
  270. if (!lua_isnumber(L,-1)) {
  271. printf("Invalid component in background color.\n");
  272. return;
  273. }
  274. int g = (int)(lua_tonumber(L,-1) * 255);
  275. lua_pop(L,1);//table
  276.  
  277. lua_getfield(L,-1,"b");//table 0.4
  278. if (!lua_isnumber(L,-1)) {
  279. printf("Invalid component in background color.\n");
  280. return;
  281. }
  282. int b = (int)(lua_tonumber(L,-1) * 255);
  283. printf("r = %d, g = %d, b = %d\n",r,g,b);
  284. lua_pop(L,1);//table
  285. lua_pop(L,1);//nil
  286.  
  287. lua_close(L);
  288. }
  289. //////////////////////////////////////////////////////////////////////////
  290. void test_lua_call_c_fun()
  291. {
  292. const char* testfunc = "print(add2(1.0,2.0)) print(sub2(20.1,19))";
  293. lua_State* L = luaL_newstate();
  294. luaL_openlibs(L);
  295. //将指定的函数注册为Lua的全局函数变量,其中第一个字符串参数为Lua代码在调用C函数时使用的全局函数名
  296. //,第二个参数为实际C函数的指针。
  297. lua_register(L, "add2", add2);
  298. lua_register(L, "sub2", sub2);
  299. //在注册完所有的C函数之后,即可在Lua的代码块中使用这些已经注册的C函数了。
  300. if (luaL_dostring(L,testfunc))
  301. printf("Failed to invoke.\n");
  302. lua_close(L);
  303. }
  304. //////////////////////////////////////////////////////////////////////////
  305. //lua文件里的print被C调用时,是可以打印到终端的!!!
  306. void test_lua_call_c_dll_fun()
  307. {
  308. lua_State* L = luaL_newstate();
  309. luaL_openlibs(L);
  310. if(luaL_dofile(L,"lua_call_c.lua"))
  311. printf("load lua_call_c.lua failed\n");;
  312. lua_close(L);
  313. }
  314.  
  315. #define BITS_PER_WORD (CHAR_BIT * sizeof(int))
  316. #define I_WORD(i) ((unsigned int)(i))/BITS_PER_WORD
  317. #define I_BIT(i) (1 << ((unsigned int)(i)%BITS_PER_WORD))
  318.  
  319. typedef struct NumArray {
  320. int size;
  321. unsigned int values[1];
  322. } NumArray;
  323.  
  324. extern "C" int newArray(lua_State* L)
  325. {
  326. //1. 检查第一个参数是否为整型。以及该参数的值是否大于等于1.
  327. int n = luaL_checkint(L,1);
  328. luaL_argcheck(L, n >= 1, 1, "invalid size.");
  329. size_t nbytes = sizeof(NumArray) + I_WORD(n - 1) * sizeof(int);
  330. //2. 参数表示Lua为userdata分配的字节数。同时将分配后的userdata对象压入栈中。
  331. NumArray* a = (NumArray*)lua_newuserdata(L,nbytes);
  332. a->size = n;
  333. for (int i = 0; i < I_WORD(n - 1); ++i)
  334. a->values[i] = 0;
  335. //获取注册表变量myarray,该key的值为metatable。
  336. luaL_getmetatable(L,"myarray");
  337. //将userdata的元表设置为和myarray关联的table。同时将栈顶元素弹出。
  338. lua_setmetatable(L,-2);
  339. return 1;
  340. }
  341.  
  342. extern "C" int setArray(lua_State* L)
  343. {
  344. //1. Lua传给该函数的第一个参数必须是userdata,该对象的元表也必须是注册表中和myarray关联的table。
  345. //否则该函数报错并终止程序。
  346. NumArray* a = (NumArray*)luaL_checkudata(L,1,"myarray");
  347. int index = luaL_checkint(L,2) - 1;
  348. //2. 由于任何类型的数据都可以成为布尔值,因此这里使用any只是为了确保有3个参数。
  349. luaL_checkany(L,3);
  350. luaL_argcheck(L,a != NULL,1,"'array' expected.");
  351. luaL_argcheck(L,0 <= index && index < a->size,2,"index out of range.");
  352. if (lua_toboolean(L,3))
  353. a->values[I_WORD(index)] |= I_BIT(index);
  354. else
  355. a->values[I_WORD(index)] &= ~I_BIT(index);
  356. return 0;
  357. }
  358.  
  359. extern "C" int getArray(lua_State* L)
  360. {
  361. NumArray* a = (NumArray*)luaL_checkudata(L,1,"myarray");
  362. int index = luaL_checkint(L,2) - 1;
  363. luaL_argcheck(L, a != NULL, 1, "'array' expected.");
  364. luaL_argcheck(L, 0 <= index && index < a->size,2,"index out of range");
  365. lua_pushboolean(L,a->values[I_WORD(index)] & I_BIT(index));
  366. return 1;
  367. }
  368.  
  369. extern "C" int getSize(lua_State* L)
  370. {
  371. NumArray* a = (NumArray*)luaL_checkudata(L,1,"myarray");
  372. luaL_argcheck(L,a != NULL,1,"'array' expected.");
  373. lua_pushinteger(L,a->size);
  374. return 1;
  375. }
  376.  
  377. extern "C" int array2string(lua_State* L)
  378. {
  379. NumArray* a = (NumArray*)luaL_checkudata(L,1,"myarray");
  380. lua_pushfstring(L,"array(%d)",a->size);
  381. return 1;
  382. }
  383.  
  384. static luaL_Reg arraylib_f [] = {
  385. {"new", newArray},
  386. {NULL, NULL}
  387. };
  388.  
  389. static luaL_Reg arraylib_m [] = {
  390. {"set", setArray},
  391. {"get", getArray},
  392. {"size", getSize},
  393. {"__tostring", array2string}, //print(a)时Lua会调用该元方法。
  394. {NULL, NULL}
  395. };
  396.  
  397. int luaopen_testuserdata(lua_State* L)
  398. {
  399. //1. 创建元表,并将该元表指定给newArray函数新创建的userdata。在Lua中userdata也是以table的身份表现的。
  400. //这样在调用对象函数时,可以通过验证其metatable的名称来确定参数userdata是否合法。
  401. luaL_newmetatable(L,"myarray");
  402. lua_pushvalue(L,-1);
  403. //2. 为了实现面对对象的调用方式,需要将元表的__index字段指向自身,同时再将arraylib_m数组中的函数注册到
  404. //元表中,之后基于这些注册函数的调用就可以以面向对象的形式调用了。
  405. //lua_setfield在执行后会将栈顶的table弹出。
  406. lua_setfield(L,-2,"__index");
  407. //将这些成员函数注册给元表,以保证Lua在寻找方法时可以定位。NULL参数表示将用栈顶的table代替第二个参数。
  408. luaL_newlib(L,arraylib_m);
  409. //这里只注册的工厂方法。
  410. luaL_newlib(L,arraylib_f);
  411. return 1;
  412. }
  413. int main()
  414. {
  415. test_c_call_lua_fun_noParam();
  416. test_c_call_lua_fun_withParam();
  417. test_c_call_lua_fun_withParam2();
  418. test_c_use_lua_variant();
  419. test_c_use_lua_table();
  420. test_c_new_lua_table();
  421. test_lua_call_c_fun();
  422. test_lua_call_c_dll_fun();
  423. getchar();
  424. return 0;
  425. }

lua52 C API测试代码的更多相关文章

  1. API 测试的具体实现

    目录 API 测试的具体实现 基于 Spring Boot 构建的 API 使用 cURL 命令行工具进行测试 使用图形界面工具 Postman 进行测试 如何应对复杂场景的 API 测试? 总结 A ...

  2. Go项目的测试代码2(项目运用)

    上一篇文章介绍了最基本的测试代码的写法.Go项目的测试代码(基础) 这里简单的共享一下我在项目中使用的方式. 项目结构 我们实际项目中, 结构简单地分了控制层controllers和模块层models ...

  3. .NET单元测试的艺术-3.测试代码

    开篇:上一篇我们学习单元测试和核心技术:存根.模拟对象和隔离框架,它们是我们进行高质量单元测试的技术基础.本篇会集中在管理和组织单元测试的技术,以及如何确保在真实项目中进行高质量的单元测试. 系列目录 ...

  4. 使用python+pychram进行API测试(接口测试)初级STEP 1

    花了一天时间安装了解了下最基本的python+pychram进行API测试,下面这个可以指导自己以后入门:基本的开发级别还需要学习 1.python下载地址:https://www.python.or ...

  5. asp.net web api 测试帮助页面建立并测试

    asp.net web api 测试帮助页面建立并测试 现在使用WEB API来开发,越来越流行. 在开发过程中的测试调试,可以使用Fiddler等工具来帮助测试外,还有: 在asp.net 中有种方 ...

  6. API测试自动化——基于CDIF的SOA基本功能(实例篇)

    今天我们通过一些实例来体验一下API的自动化测试,感受一下基于CDIF的SOA的一些基本功能. 传统的测试工具在测试一个API的时候,必须手动填写这个API所需要接收的所有信息,比如一个查询航班动态的 ...

  7. 开源API测试工具 Hitchhiker v0.6更新 - 改进压力测试

    Hitchhiker 是一款开源的支持多人协作的 Restful Api 测试工具,支持Schedule, 数据对比,压力测试,支持上传脚本定制请求,可以轻松部署到本地,和你的team成员一起协作测试 ...

  8. 开源API测试工具 Hitchhiker v0.7更新 - Schedule的对比diff

    Hitchhiker 是一款开源的支持多人协作的 Restful Api 测试工具,支持Schedule, 数据对比,压力测试,支持脚本定制请求,可以轻松部署到本地,和你的team成员一起协作测试Ap ...

  9. 开源API测试工具 Hitchhiker v0.8 - 自动化测试结果统计

    Hitchhiker 是一款开源的支持多人协作的 Restful Api 测试工具,支持自动化测试, 数据对比,压力测试,支持脚本定制请求,可以轻松部署到本地,和你的team成员一起协作测试Api. ...

随机推荐

  1. 1 云计算系列之云计算概述和KVM虚拟化简介

    为什么会出现云之传统数据中学面临的问题 物理服务器的利用率非常低,浪费资源,且资源分配不合理,比如一台服务器CPU使用率不到40%,或者某个应用需要的硬件配置低但是服务器硬件配置高等等. 云计算概念 ...

  2. <<< Oracle表空间创建、修改、删除基本操作

    ORACLE 中,表空间是数据管理的基本方法,所有用户的对象要存放在表空间中,也就是用户有空间的使用权,才能创建用户对象 create tablespace myts  //建立表空间,名为mytsd ...

  3. Socket异步通讯

    1.可以通过多线程来解决(一会补上) 2.Socket在tcp/udp两种通信协议下的异步通信: 基于TCP的异步通信: BeginAccept方法和endeaccept方法 包含在System.Ne ...

  4. Redis主-从部署实践

    0. 前言 这篇文章简要介绍Redis的主从部署,实现了一主二从,使用两个哨兵监控,以实现简单的HA,其中从库作为备机. 1. 部署 这里有三台服务器,其中239主机上的Redis作为主库,其余两个作 ...

  5. Unable to load configuration. - Class: java.net.AbstractPlainSocketImpl

    [Bug笔记]Unable to load configuration. - Class: java.net.AbstractPlainSocketImpl 标签: bugjartomcat服务器互联 ...

  6. Centos6.5 Zabbix3 server端安装(一)

    一.准备阶段: 1.>关闭防火墙 /etc/init.d/iptables stop 2.>关闭selinux vim /etc/selinux/config SELINUX=disabl ...

  7. FireFox每次访问页面时检查最新版本

    FireFox每次访问页面时检查最新版本 浏览器都有自己的缓存机制,作为开发人员,每次js的修改都要清空缓存,显然很不方便.而firefox并没有提供ie那样的设置. 下面的方法就可以非常方便的设置f ...

  8. 学习MySQL之单表操作(二)

    ##单表操作 ##创建表 CREATE TABLE t_employee( empno ), ename ), job ), MGR ), Hiredate DATE DEFAULT '0000-00 ...

  9. 【piu~】制作一只变形小鸡~

    在http://codepen.io/pick上看到的,,,具体是谁忘了,反正我只截了最萌的一段,作者越改越不萌ಥ_ಥ 谷哥哥随便一搜就有很多好玩的,度娘就...(  ̄ ▽ ̄)o╭╯☆#╰ _─﹏─) ...

  10. 微信公众平台"微信连Wi-Fi"功能来了 线下微信增粉利器

    微信连Wi-Fi功能在第三方开发者和服务商已经有出现了,但有些成本相对会高些.近日微信公众平台新添了一个功能插件“微信连Wi-Fi”,已有微信认证过的公众号即可申请开通.赶紧去布局这个线下微信增粉利器 ...