//这是一篇lua与C++交互的情景测试
#include <lua.hpp>
#include <lauxlib.h>
#include <lualib.h>
#include <string.h>
#include <limits.h> #pragma region not_importent_
static void stackDump (lua_State *L)
{
int i;
int top = lua_gettop(L);
for(i=1;i<=top;i++){
/*repeatforeachlevel*/
int t = lua_type(L, i);
switch (t) {
case LUA_TSTRING:
/* strings */
printf("`%s'", lua_tostring(L, i));
break;
case LUA_TBOOLEAN:
/* booleans */
printf(lua_toboolean(L, i) ? "true" : "false");
break;
case LUA_TNUMBER:
/* numbers */
printf("%g", lua_tonumber(L, i));
break;
default:
/* other values */
printf("%s", lua_typename(L, t));
break;
}
printf(" ");
/* put a separator */
}
printf("\n");
/* end the listing */
} void error (lua_State *L, const char *fmt, const char *str) {
printf(fmt, str);
}
//待Lua调用的C注册函数。
static int add2(lua_State* L)
{
//检查栈中的参数是否合法,1表示Lua调用时的第一个参数(从左到右),依此类推。
//如果Lua代码在调用时传递的参数不为number,该函数将报错并终止程序的执行。
double op1 = luaL_checknumber(L,1);
double op2 = luaL_checknumber(L,2);
//将函数的结果压入栈中。如果有多个返回值,可以在这里多次压入栈中。
lua_pushnumber(L,op1 + op2);
//返回值用于提示该C函数的返回值数量,即压入栈中的返回值数量。
return 1;
}
static int sub2(lua_State* L)
{
double op1 = luaL_checknumber(L,1);
double op2 = luaL_checknumber(L,2);
lua_pushnumber(L,op1 - op2);
return 1;
}
#pragma endregion //////////////////////////////////////////////////////////////////////////
void test_c_call_lua_fun_noParam()
{
const char* buff = "print(\"hello\")";
int err; //init
lua_State* L = luaL_newstate();
luaL_openlibs(L); //load buff
err = luaL_loadbuffer(L,buff,strlen(buff),"line") ;
err += lua_pcall(L,0,0,0);
int s = lua_gettop(L);
if(err){
fprintf(stderr,"%s",lua_tostring(L,-1));
lua_pop(L,1);
} //close
lua_close(L); }
//////////////////////////////////////////////////////////////////////////
void test_c_call_lua_fun_withParam()
{
lua_State *L = luaL_newstate();
luaL_openlibs(L);
if (luaL_loadfile(L, "luafile2.lua") || lua_pcall(L, 0, 0, 0))
{
error(L, "cannot run configuration file: %s",lua_tostring(L, -1));
return;
}
lua_getglobal(L, "do_lua_kk");
lua_getglobal(L, "a");
lua_getglobal(L, "do_lua_error");
lua_getglobal(L, "b");
lua_getglobal(L, "do_c_one");
lua_getglobal(L, "do_c");
lua_getglobal(L, "width");
lua_getglobal(L, "height");
// lua_getglobal(L, "do_c_two");
stackDump(L); //打印结果:function `lua_str_a' function `lua_str_b' function function 999 300
int k = 100; k = lua_pcall(L, 2, 1, 1);
stackDump(L); //打印结果:function `lua_str_a' function `lua_str_b' function 8888
/*lua 执行栈上最上面的函数,使用栈上2个参数,向栈压入3个返回值
使用栈上第1位置的函数do_lua_kk作为错误处理回调函数,输出:
-------->do_c
999--add--300-->--2222
*/
k = lua_pcall(L, 1, 0, 0);
stackDump(L); lua_close(L);
}
//////////////////////////////////////////////////////////////////////////
void test_c_call_lua_fun_withParam2()
{
lua_State* L = luaL_newstate(); //luaL_dostring 等同于luaL_loadstring() || lua_pcall()
//注意:在能够调用Lua函数之前必须执行Lua脚本,否则在后面实际调用Lua函数时会报错,
//错误信息为:"attempt to call a nil value."
const char* lua_function_code = "function add(x,y) return x + y end";
if (luaL_dostring(L,lua_function_code)) {
printf("Failed to run lua code.\n");
return;
}
double x = 1.0, y = 2.3;
lua_getglobal(L,"add");
lua_pushnumber(L,x);
lua_pushnumber(L,y);
//下面的第二个参数表示带调用的lua函数存在两个参数。
//第三个参数表示即使带调用的函数存在多个返回值,那么也只有一个在执行后会被压入栈中。
//lua_pcall调用后,虚拟栈中的函数参数和函数名均被弹出。
if (lua_pcall(L,2,1,0)) {
printf("error is %s.\n",lua_tostring(L,-1));
return;
}
//此时结果已经被压入栈中。
if (!lua_isnumber(L,-1)) {
printf("function 'add' must return a number.\n");
return;
}
double ret = lua_tonumber(L,-1);
lua_pop(L,-1); //弹出返回值。
printf("The result of call function is %f.\n",ret);
lua_close(L); }
//////////////////////////////////////////////////////////////////////////
void test_c_use_lua_variant()
{
const char* luascript = "width=111 ; height=222";
lua_State* L = luaL_newstate();
int w,h;
//luaL_loadfile的作用是编译lua文件为一个chunk
//把这个chunk当作一个匿名函数压在栈上
//lua_pcall的作用是执行这个匿名函数,然后才能取得栈上的值
if(luaL_loadstring(L,luascript) || lua_pcall(L,0,0,0)){
printf("Error msg is %s.\n",lua_tostring(L,-1));
return;
}
lua_getglobal(L,"width"); //调用次函数,则把全局变量压栈
lua_getglobal(L,"height");//这里压栈次序决定了后面取值的索引
if(!lua_isnumber(L,-2)){
printf("width must be number\n");
return;
}
if(!lua_isnumber(L,-1)){
printf("height must be number\n");
return ;
}
w = lua_tointeger(L,-2);
h = lua_tointeger(L,-1); printf("width = %d height = %d\n",w,h);
lua_close(L);
}
//////////////////////////////////////////////////////////////////////////
void test_c_use_lua_table()
{
lua_State* L = luaL_newstate();
if (luaL_loadstring(L,"background = { r = 0.30, g = 0.10, b = 0 }")
|| lua_pcall(L,0,0,0)) {
printf("Error Msg is %s.\n",lua_tostring(L,-1));
return;
}
lua_getglobal(L,"background");
if (!lua_istable(L,-1)) {
printf("'background' is not a table.\n" );
return;
}
//下面取栈上的table内容
lua_getfield(L,-1,"r");
if (!lua_isnumber(L,-1)) {
printf("Invalid component in background color.\n");
return;
}
int r = (int)(lua_tonumber(L,-1) * 255);
lua_pop(L,1);//出栈 lua_getfield(L,-1,"g");
if (!lua_isnumber(L,-1)) {
printf("Invalid component in background color.\n");
return;
}
int g = (int)(lua_tonumber(L,-1) * 255);
lua_pop(L,1); lua_pushnumber(L,0.4);//入栈,栈顶位置-1的值是0.4
lua_setfield(L,-2,"b");//设置background["b"]=0.4,注意-2这个位置表示table的位置!!
lua_getfield(L,-1,"b");//取table值
stackDump(L);
if (!lua_isnumber(L,-1)) {
printf("Invalid component in background color.\n");
return;
}
int b = (int)(lua_tonumber(L,-1) * 255);
printf("r = %d, g = %d, b = %d\n",r,g,b);
lua_pop(L,1);
stackDump(L);
lua_pop(L,1); //栈被清空了 lua_close(L);
}
//////////////////////////////////////////////////////////////////////////
void test_c_new_lua_table()
{
lua_State* L = luaL_newstate();
lua_newtable(L);//Lua会生成一个新的table对象并将其压入栈中。
lua_pushnumber(L,0.3);
stackDump(L);//table 0.3
lua_setfield(L,-2,"r");//设置table["r"]=0.3完了把0.3弹出
stackDump(L);//table lua_pushnumber(L,0.1);
lua_setfield(L,-2,"g"); lua_pushnumber(L,0.4);
lua_setfield(L,-2,"b"); stackDump(L);//table
lua_setglobal(L,"background");//栈顶元素出栈
stackDump(L);//nil
//调用该宏后,Lua会将当前栈顶的值赋值给第二个参数指定的全局变量名。
//该宏在执行成功后,会将刚刚赋值的值从栈顶弹出。 lua_getglobal(L,"background");//把background压栈
stackDump(L);//table
if (!lua_istable(L,-1)) {
printf("'background' is not a table.\n" );
return;
}
lua_getfield(L,-1,"r");//table["r"]压栈
stackDump(L);//table 0.3
if (!lua_isnumber(L,-1)) {
printf("Invalid component in background color.\n");
return;
}
int r = (int)(lua_tonumber(L,-1) * 255);
lua_pop(L,1);//table lua_getfield(L,-1,"g");//table 0.1
if (!lua_isnumber(L,-1)) {
printf("Invalid component in background color.\n");
return;
}
int g = (int)(lua_tonumber(L,-1) * 255);
lua_pop(L,1);//table lua_getfield(L,-1,"b");//table 0.4
if (!lua_isnumber(L,-1)) {
printf("Invalid component in background color.\n");
return;
}
int b = (int)(lua_tonumber(L,-1) * 255);
printf("r = %d, g = %d, b = %d\n",r,g,b);
lua_pop(L,1);//table
lua_pop(L,1);//nil lua_close(L);
}
//////////////////////////////////////////////////////////////////////////
void test_lua_call_c_fun()
{
const char* testfunc = "print(add2(1.0,2.0)) print(sub2(20.1,19))";
lua_State* L = luaL_newstate();
luaL_openlibs(L);
//将指定的函数注册为Lua的全局函数变量,其中第一个字符串参数为Lua代码在调用C函数时使用的全局函数名
//,第二个参数为实际C函数的指针。
lua_register(L, "add2", add2);
lua_register(L, "sub2", sub2);
//在注册完所有的C函数之后,即可在Lua的代码块中使用这些已经注册的C函数了。
if (luaL_dostring(L,testfunc))
printf("Failed to invoke.\n");
lua_close(L);
}
//////////////////////////////////////////////////////////////////////////
//lua文件里的print被C调用时,是可以打印到终端的!!!
void test_lua_call_c_dll_fun()
{
lua_State* L = luaL_newstate();
luaL_openlibs(L);
if(luaL_dofile(L,"lua_call_c.lua"))
printf("load lua_call_c.lua failed\n");;
lua_close(L);
} #define BITS_PER_WORD (CHAR_BIT * sizeof(int))
#define I_WORD(i) ((unsigned int)(i))/BITS_PER_WORD
#define I_BIT(i) (1 << ((unsigned int)(i)%BITS_PER_WORD)) typedef struct NumArray {
int size;
unsigned int values[1];
} NumArray; extern "C" int newArray(lua_State* L)
{
//1. 检查第一个参数是否为整型。以及该参数的值是否大于等于1.
int n = luaL_checkint(L,1);
luaL_argcheck(L, n >= 1, 1, "invalid size.");
size_t nbytes = sizeof(NumArray) + I_WORD(n - 1) * sizeof(int);
//2. 参数表示Lua为userdata分配的字节数。同时将分配后的userdata对象压入栈中。
NumArray* a = (NumArray*)lua_newuserdata(L,nbytes);
a->size = n;
for (int i = 0; i < I_WORD(n - 1); ++i)
a->values[i] = 0;
//获取注册表变量myarray,该key的值为metatable。
luaL_getmetatable(L,"myarray");
//将userdata的元表设置为和myarray关联的table。同时将栈顶元素弹出。
lua_setmetatable(L,-2);
return 1;
} extern "C" int setArray(lua_State* L)
{
//1. Lua传给该函数的第一个参数必须是userdata,该对象的元表也必须是注册表中和myarray关联的table。
//否则该函数报错并终止程序。
NumArray* a = (NumArray*)luaL_checkudata(L,1,"myarray");
int index = luaL_checkint(L,2) - 1;
//2. 由于任何类型的数据都可以成为布尔值,因此这里使用any只是为了确保有3个参数。
luaL_checkany(L,3);
luaL_argcheck(L,a != NULL,1,"'array' expected.");
luaL_argcheck(L,0 <= index && index < a->size,2,"index out of range.");
if (lua_toboolean(L,3))
a->values[I_WORD(index)] |= I_BIT(index);
else
a->values[I_WORD(index)] &= ~I_BIT(index);
return 0;
} extern "C" int getArray(lua_State* L)
{
NumArray* a = (NumArray*)luaL_checkudata(L,1,"myarray");
int index = luaL_checkint(L,2) - 1;
luaL_argcheck(L, a != NULL, 1, "'array' expected.");
luaL_argcheck(L, 0 <= index && index < a->size,2,"index out of range");
lua_pushboolean(L,a->values[I_WORD(index)] & I_BIT(index));
return 1;
} extern "C" int getSize(lua_State* L)
{
NumArray* a = (NumArray*)luaL_checkudata(L,1,"myarray");
luaL_argcheck(L,a != NULL,1,"'array' expected.");
lua_pushinteger(L,a->size);
return 1;
} extern "C" int array2string(lua_State* L)
{
NumArray* a = (NumArray*)luaL_checkudata(L,1,"myarray");
lua_pushfstring(L,"array(%d)",a->size);
return 1;
} static luaL_Reg arraylib_f [] = {
{"new", newArray},
{NULL, NULL}
}; static luaL_Reg arraylib_m [] = {
{"set", setArray},
{"get", getArray},
{"size", getSize},
{"__tostring", array2string}, //print(a)时Lua会调用该元方法。
{NULL, NULL}
}; int luaopen_testuserdata(lua_State* L)
{
//1. 创建元表,并将该元表指定给newArray函数新创建的userdata。在Lua中userdata也是以table的身份表现的。
//这样在调用对象函数时,可以通过验证其metatable的名称来确定参数userdata是否合法。
luaL_newmetatable(L,"myarray");
lua_pushvalue(L,-1);
//2. 为了实现面对对象的调用方式,需要将元表的__index字段指向自身,同时再将arraylib_m数组中的函数注册到
//元表中,之后基于这些注册函数的调用就可以以面向对象的形式调用了。
//lua_setfield在执行后会将栈顶的table弹出。
lua_setfield(L,-2,"__index");
//将这些成员函数注册给元表,以保证Lua在寻找方法时可以定位。NULL参数表示将用栈顶的table代替第二个参数。
luaL_newlib(L,arraylib_m);
//这里只注册的工厂方法。
luaL_newlib(L,arraylib_f);
return 1;
}
int main()
{
test_c_call_lua_fun_noParam();
test_c_call_lua_fun_withParam();
test_c_call_lua_fun_withParam2();
test_c_use_lua_variant();
test_c_use_lua_table();
test_c_new_lua_table();
test_lua_call_c_fun();
test_lua_call_c_dll_fun();
getchar();
return 0;
}

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. Spring系列之谈谈对Spring IOC的理解

    学习过Spring框架的人一定都会听过Spring的IoC(控制反转) .DI(依赖注入)这两个概念,对于初学Spring的人来说,总觉得IOC .DI这两个概念是模糊不清的,是很难理解的,今天和大家 ...

  2. JS高级群的日常!写一个从10到0的倒计时,用console.log打印,不可以用 setInterval!本来说好的研究avalonJS最后演变成了看着大神在那边互相比拼实力。。

      JS高级群的日常!写一个从10到0的倒计时,用console.log打印,不可以用 setInterval!本来说好的研究avalonJS最后演变成了看着大神在那边互相比拼实力..   小森执行一 ...

  3. Python 爬虫2

    import urllib.request import os import re import time 设置头文件 head={} head['User-Agent'] ='Mozilla/5.0 ...

  4. Navigation Bar options for Android (based on photosomething project)

    1, Tab控件即标签页,可以在一页中切换显示n页内容,要使用此效果,需要用到TabHost和Tabwidget类.(过时了?) Tab控件具有两种实现过程,一是在同一个Activity中切换显示不同 ...

  5. 常用的Javascript设计模式

    <parctical common lisp>的作者曾说,如果你需要一种模式,那一定是哪里出了问题.他所说的问题是指因为语言的天生缺陷,不得不去寻求和总结一种通用的解决方案. 不管是弱类型 ...

  6. AssetBundle loading failed because.....已解决

    http://blog.csdn.net/ldghd/article/details/9632455 *****************************      一      ******* ...

  7. 百度地图SDK

      百度地图官方SDK文档 http://lbsyun.baidu.com/index.php?title=androidsdk   一.申请百度地图SDK 每一个app对应一个百度地图AK,百度地图 ...

  8. ACM/ICPC 之 Unix会议室(POJ1087)

    采用EK算法解网络流经典题,本题构图思路比较明确. //Unix会议室插座转换 //网络流-EK算法 //Time:47Ms Memory:1188K #include<iostream> ...

  9. Path之Data属性语法A命令

    <Path Width="300" Height="300" Fill="Red" Data="M 100,100 L 10 ...

  10. 解决SprngMVC中ResponseBody注解中文乱码

    配置文件前面加入如下结构,版本号3.2.5 <bean class="org.springframework.web.servlet.mvc.method.annotation.Req ...