每日一Lua(6)-lua与c的交互及学习总结

每日一Lua(6)-lua与c的交互及学习总结,第1张

概述       lua作为小巧精悍的脚本语言,易于嵌入c/c++中 , 广泛应用于游戏AI ,实际上在任何经常变化的逻辑上都可以使用lua实现,配合c/c++实现的底层接口服务,能够大大降低系统的维护成本。       lua和c/c++的数据交互通过"栈"进行 , *** 作数据时,首先将数据拷贝到"栈"上,然后获取数据,栈中的每个数据通过索引值进行定位,索引值为正时表示相对于栈底的偏移索引,索引值为负时

       lua作为小巧精悍的脚本语言,易于嵌入c/c++中 , 广泛应用于游戏AI ,实际上在任何经常变化的逻辑上都可以使用lua实现,配合c/c++实现的底层接口服务,能够大大降低系统的维护成本。

      lua和c/c++的数据交互通过"栈"进行, *** 作数据时,首先将数据拷贝到"栈"上,然后获取数据,栈中的每个数据通过索引值进行定位,索引值为正时表示相对于栈底的偏移索引,索引值为负时表示相对于栈顶的偏移索引,索引值以1或-1为起始值,因此栈顶索引值永远为-1,栈底索引值永远为1 。 "栈"相当于数据在lua和c/c++之间的中转地。每种数据都有相应的存取接口 。

C调用lua中的方法

lua中存储了需要调用的函数

function add(x,y)	print("sum:"..x+y)	return x+yend

C语言对其进行调用
#include <lua.hpp>#include <stdio.h>int main(){	int a=10,b=20;	int result=0;	lua_State *L = luaL_newstate();	luaopen_base(L);	luaL_dofile(L,"scene.lua");	lua_getglobal(L,"add");	lua_pushinteger(L,a);	lua_pushinteger(L,b);	lua_pcall(L,2,1,0);	result=(int)lua_tonumber(L,-1);        lua_close( L);	printf("result:%d\n",result);}


运行结果:

一行一行解释.

1.包含lua的头文件;

2.添加标准输入输出;

5,6.初始化两个变量;

7.创建lua运行环境;

8.加载基本库;

9.加载lua脚本;

10.获取全局变量;

11,12.传入参数到栈;

13.调用函数,不处理结果;

14.结果出栈;

15.关闭lua;

16.打印结果。

C中获取lua中的数据

lua文件用于存储配置文件。

app_name="testApp"ID=1host_info={hostname="SuperMan",ip="128.0.0.1",}data={	date="2013.2",user="Jack"}host_info.content=dataprint("Load .lua successful!")

配置文件中包含字符串,数字还有一个嵌套的table。

下面是用c来解析:

#include <lua.hpp>#include <stdio.h>int table_next(lua_State *L,int i,char **k,char **v){	if ( lua_next(L,i) !=0 )	{		*k = (char *)lua_tostring(L,-2);		*v = (char *)lua_tostring(L,-1);		lua_pop(L,1);		return 1;	}	else	return 0;}int main(){	int ID=0;	int ret = 0 ;	char *k=NulL;	char *v=NulL;	lua_State *L = luaL_newstate();	luaopen_base(L);	luaL_dofile(L,"s.lua");	lua_pcall(L,0);	lua_getglobal(L,"app_name");	printf("application name is %s.\n",lua_tostring(L,-1));	lua_pop(L,1);		lua_getglobal(L,"host_info");	lua_getfIEld(L,-1,"hostname");	lua_getfIEld(L,-2,"ip");	printf("Host name is %s,ip is %s.\n",-2),2);		lua_pushnil(L);	printf("istable:%d\n",lua_istable(L,-2));	while(lua_next(L,-2))	{		printf("Get key %s\n",-2));		if(lua_istable(L,-1))		{		printf("Is table!\n");		lua_getfIEld(L,"date");		lua_getfIEld(L,"user");		printf("\tuser:%s\n",-1));		printf("\tdate:%s\n",-2));		lua_pop(L,2);		}		else		{			printf("value is:%s\n",-1)); 		}		lua_pop(L,1);	}	lua_close(L);	}


在这里一定要理解交互中的栈模型。

几个重要的函数:

lua_pushnil(lua_State *lua);

pushnil就是向栈中压入Lua的nil,nil在Lua中是一个类型值,在C中,大家可以 将其视为NulL,并且像lua_tostring这样的从栈中未取到值,也就是Lua中的nil,得到的结果就是NulL。

 lua_next(lua_State *lua,int index)

lua_next(lua_State *lua,int index)函数是这个例子的主角,他可以根据指定交互栈中index处的table,进行遍历,每次取(-1)位置的一个key作为前辈,即将要取得一对元素的上一对元素的key,然后返回table的该 对元素,将其键先压入栈,再将该键对应的值压入栈,结果就是(-2)位置放的是键,(-1)位置放的是值。table自然被压入到其后,本例中的(-3)位置。如果key为nil,则默认为首对数据, 会随机的压入一对值。当所有值都被遍历一遍后,next返回0。

lua_pop(lua_State *lua,int num)

该函数如上面所述:从交互句柄的交互栈中d出num个值。这里不得不说下Lua作配置文件的另一个好处-Lua自己处理堆栈,使得配置文件程序更安全。所有压入栈中的内容,只要 调用该函数,Lua就是自己对其内存进行处理,无需程序员得干预,当然,这样也说明了,不可以带走栈中的内存,也就是不可以将栈中d出来的内存如字符串内存用作他用,否则可能 在pop后,该内存将失效。


lua_getfIEld(lua,"name"); 该API主要是用来处理table。其第一个参数是交互的句柄,第二个参数是table在交互的栈的位置,第三个参数是前面table中的键。 该函数的结果是将该table中对于键的值取出来,并压入到交互栈中。这样就使得原来位于(-1)位置的table就下压了一个位置到了 (-2)。

关于嵌套table的读取,代码中首先是读取了host_info这个table,当前处于栈的-1的位置,然后pushnil之后,table变为-2的位置,调用next之后,压入一对key-value,可以在-2的位置,value在-1,之前的顺次后移。

知道了位置之后就可以通过相应的get获取值了。


lua调用c库

首先用C写好要注册的函数。

#include <lua.hpp>#include <math.h>#include <stdio.h>typedef int (*lua_CFunction)(lua_State *L);static int l_sin(lua_State *L) { double d = luaL_checknumber(L,1); lua_pushnumber(L,sin(d)); return 1; /* number of results */}static const struct luaL_Reg mylib[]= { {"lsin",l_sin},{NulL,NulL}/* 必须以NulL结尾 */};extern int luaopen_mylib (lua_State *L) { //lua_register(L,"mylib",mylib);  //luaL_openlib(L,mylib,0);  luaL_register(L,mylib); return 1;}

理论上编译成.so文件即可在lua中调用,但在编译的时候一直报错:

test3.c: In function ‘int luaopen_mytestlib(lua_State*)’:test3.c:44:6: error: cannot convert ‘luaL_Reg*’ to ‘lua_CFunction {aka int (*)(lua_State*)}’ for argument ‘2’ to ‘voID lua_pushcclosure(lua_State*,lua_CFunction,int)’

至今尚未解决....


lua学习阶段总结

学lua的动机只是因为一句话——合格的程序员应该至少每年学习一门语言!

学得不是很深,大部分的时候都是参照网上的例子敲一些代码,有些需要花时间去理解的地方也没有深究,但至少算是基本掌握了一门脚本语言,以后要用到的话再捡起来也会很快。

总结

以上是内存溢出为你收集整理的每日一Lua(6)-lua与c的交互及学习总结全部内容,希望文章能够帮你解决每日一Lua(6)-lua与c的交互及学习总结所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1265487.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-08
下一篇 2022-06-08

发表评论

登录后才能评论

评论列表(0条)

保存