『Game』lua和c/c++互相调用实例分析
来源:互联网 发布:caffe axis 编辑:程序博客网 时间:2024/06/05 06:23
原文地址:lua和c/c++互相调用实例分析
lua作为小巧精悍的脚本语言,易于嵌入c/c++中 , 广泛应用于游戏AI ,实际上在任何经常变化的逻辑上(其灵活性可应对经常变化的逻辑,在lua与c交互上也得有办法,让它们易用才行。)都可以使用lua实现,配合c/c++实现的底层接口服务,能够大大降低系统的维护成本。下面对lua和c/c++的交互调用做一个实例分析:
lua提供了API用于在c/c++中构造lua的运行环境,相关接口如下:
//创建lua运行上下文
lua_State* luaL_newstate(void) ;
//加载lua脚本文件
int luaL_loadfile(lua_State *L, const char *filename);
lua和c/c++的数据交互通过"栈"进行 ,操作数据时,首先将数据拷贝到"栈"上,然后获取数据,栈中的每个数据通过索引值进行定位,索引值为正时表示相对于栈底的偏移索引,索引值为负时表示相对于栈顶的偏移索引,索引值以1或-1为起始值,因此栈顶索引值永远为-1 ,栈底索引值永远为1 。 "栈"相当于数据在lua和c/c++之间的中转地。每种数据都有相应的存取接口 。
数据入"栈"接口:
void (lua_pushnil) (lua_State *L);
void (lua_pushnumber) (lua_State *L, lua_Number n);
void (lua_pushinteger) (lua_State *L, lua_Integer n);
void (lua_pushlstring) (lua_State *L, const char *s, size_t l);
void (lua_pushstring) (lua_State *L, const char *s);
void (lua_pushboolean) (lua_State *L, int b);
void (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n);
数据获取接口:
lua_Number (lua_tonumber) (lua_State *L, int idx);
lua_Integer (lua_tointeger) (lua_State *L, int idx);
int (lua_toboolean) (lua_State *L, int idx);
const char *(lua_tolstring) (lua_State *L, int idx, size_t *len);
lua_CFunction (lua_tocfunction) (lua_State *L, int idx);
"栈"操作接口:
int (lua_gettop) (lua_State *L);
void (lua_settop) (lua_State *L, int idx);
void (lua_pushvalue) (lua_State *L, int idx);
void (lua_remove) (lua_State *L, int idx);
void (lua_insert) (lua_State *L, int idx);
void (lua_replace) (lua_State *L, int idx);
int (lua_checkstack) (lua_State *L, int sz);
lua中定义的变量和函数存放在一个全局table中,索引值为LUA_GLOBALSINDEX ,table相关操作接口:
void (lua_gettable) (lua_State *L, int idx);
void (lua_getfield) (lua_State *L, int idx, const char *k);
void (lua_settable) (lua_State *L, int idx);
void (lua_setfield) (lua_State *L, int idx, const char *k);
当"栈"中包含执行脚本需要的所有要素(函数名和参数)后,调用lua_pcall执行脚本:
int (lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc);
下面进行实例说明:
func.lua
--变量定义width=1 ;height=2 ;--lua函数定义,实现加法function sum(a,b) return a+b ;end--lua函数定义,实现字符串相加function mystrcat(a,b) return a..b ;end--lua函数定义,通过调用c代码中的csum函数实现加法function mysum(a,b) return csum(a,b) ;end
test_lua.c
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <errno.h>//lua头文件#include <lua.h>#include <lualib.h>#include <lauxlib.h>#define err_exit(num,fmt,args) \ do{printf("[%s:%d]"fmt"\n",__FILE__,__LINE__,##args);exit(num);} while(0)#define err_return(num,fmt,args) \ do{printf("[%s:%d]"fmt"\n",__FILE__,__LINE__,##args);return(num);} while(0)//lua中调用的c函数定义,实现加法int csum(lua_State* l){ int a = lua_tointeger(l,1) ; int b = lua_tointeger(l,2) ; lua_pushinteger(l,a+b) ; return 1 ;}int main(int argc,char** argv){ lua_State * l = luaL_newstate() ; //创建lua运行环境 if ( l == NULL ) err_return(-1,"luaL_newstat() failed"); int ret = 0 ; ret = luaL_loadfile(l,"func.lua") ; //加载lua脚本文件 if ( ret != 0 ) err_return(-1,"luaL_loadfile failed") ; ret = lua_pcall(l,0,0,0) ; if ( ret != 0 ) err_return(-1,"lua_pcall failed:%s",lua_tostring(l,-1)) ; lua_getglobal(l,"width"); //获取lua中定义的变量 lua_getglobal(l,"height"); printf("height:%ld width:%ld\n",lua_tointeger(l,-1),lua_tointeger(l,-2)) ; lua_pop(l,1) ; //恢复lua的栈 int a = 11 ; int b = 12 ; lua_getglobal(l,"sum"); //调用lua中的函数sum lua_pushinteger(l,a) ; lua_pushinteger(l,b) ; ret = lua_pcall(l,2,1,0) ; if ( ret != 0 ) err_return(-1,"lua_pcall failed:%s",lua_tostring(l,-1)) ; printf("sum:%d + %d = %ld\n",a,b,lua_tointeger(l,-1)) ; lua_pop(l,1) ; const char str1[] = "hello" ; const char str2[] = "world" ; lua_getglobal(l,"mystrcat"); //调用lua中的函数mystrcat lua_pushstring(l,str1) ; lua_pushstring(l,str2) ; ret = lua_pcall(l,2,1,0) ; if ( ret != 0 ) err_return(-1,"lua_pcall failed:%s",lua_tostring(l,-1)) ; printf("mystrcat:%s%s = %s\n",str1,str2,lua_tostring(l,-1)) ; lua_pop(l,1) ; lua_pushcfunction(l,csum) ; //注册在lua中使用的c函数 lua_setglobal(l,"csum") ; //绑定到lua中的名字csum lua_getglobal(l,"mysum"); //调用lua中的mysum函数,该函数调用本程序中定义的csum函数实现加法 lua_pushinteger(l,a) ; lua_pushinteger(l,b) ; ret = lua_pcall(l,2,1,0) ; if ( ret != 0 ) err_return(-1,"lua_pcall failed:%s",lua_tostring(l,-1)) ; printf("mysum:%d + %d = %ld\n",a,b,lua_tointeger(l,-1)) ; lua_pop(l,1) ; lua_close(l) ; //释放lua运行环境 return 0 ;}
除去图像这一层极端效率敏感的部分外,其他部分其实用效率适当下降换取灵活是值得的
原文地址:目前服務器需要做c++和lua對接,做遊戲的童鞋有比較好的庫和類推薦嗎?
我们游戏用的是lua_tinker, 一个韩国人写根据LuaBind改的,它的优点是简单,就2个文件,并且很容易自己修改。
另外一个常用的是tolua,可以很容易把C++的类导到lua里,供lua调用,不过在C++里调用Lua不太方便。
用过LuaBind,LuaPlus,lua_tinker几个库。
LuaBind大概是05年的样子,功能最全面,效率也很好,不过恶心的是库很大,构建环境比较麻烦,而且那时候还需要Boost库的支持(现在不知道了),比较繁琐,后来不用了;
LuaPlus是之前用的比较广泛的一个库,印象里用到Lua的客户端网游,用他的比较多,特点是中庸(不是贬义);
lua_tinker是现在的游戏使用到的,的确是简单清爽的感觉,个人比较喜欢;
我个人觉得要是客户端游戏用LuaPlus比较好(比如想做那种wowUI的),服务器Lua用lua_tinker。轻量级用lua_tinker,否则就LuaPlus。
另有次无意在HomeWorld 2的游戏中看到了Lua脚本,那是2000-2002年的产物,那时候Lua还没太多人用,可见wow的影响力:(
他们改进了大话和梦幻的服务器设计,把处理连接的部分独立出来放到单独的进程中 ,使服务器性能大大提高。
原文地址:http://www.cnblogs.com/hmxp8/archive/2011/11/23/2259777.html
这一篇对lua堆栈操作讲的很通俗易懂:lua堆栈操作
(1)lua 和 C++之间的交互的基本知识:
lua 和 C++ 之间的数据交互通过堆栈进行,栈中的数据通过索引值进行定位,(栈就像是一个容器一样,放进去的东西都要有标号)
其中栈顶是-1,栈底是1,也就是第 1 个入栈的在栈底;也可以这么说:正数表示相对于栈底的位置(位移),负数表示相对于栈顶的位置(位移);
(2)计算和清空栈中元素的操作:
1、函数lua_gettop()
用于返回栈中元素的个数,同时也是栈顶元素的索引,因为栈底是1,所以栈中有多少个元素,栈顶索引就是多少;呵呵
2、函数lua_settop()
函数原型:void lua_settop(lua_State *L , int index);
用于把堆栈的栈顶索引设置为指定的数值,比如说,一个栈原来有8个元素,调用函数设置index为7,就是把堆栈的元素数设置为7,也就是删掉一个元素,而且是栈顶元素;这个是用的正数,也就是相对于栈底元素设置的;如果是相对于栈顶元素,则要求用负值;也就是说如果设置索引为-2(index = -2),也相当于删除掉栈顶元素;呵呵,画个图就很方便了;为了说明方便,干脆设置一个宏:
#define lua_pop(L,n) lua_settop(L,-(n)-1)
这里的n是相对于栈顶的第几个元素,主要是为了理解;后面的lua_settop(L,-(n)-1) 用的就是相对于栈顶位移的负数表示;
3、lua_pushvalue()
函数原型:void lua_pushvalue (lua_State *L, int index);
英文原意:Pushes a copy of the element at the given valid index onto the stack.
下面是一个例子,栈的初始状态为10 20 30 40 50 *(从栈底到栈顶,“*”标识为栈顶)有:
lua_pushvalue(L, 3) --> 10 20 30 40 50 30*
lua_pushvalue(L,3)是取得原来栈中的第三个元素,压到栈顶;
4、lua_remove()
void lua_remove(lua_State *L, int index);
lua_remove删除给定索引的元素,并将这一索引之上的元素来填补空缺;
下面是一个例子,栈的初始状态为10 20 30 40 50 *(从栈底到栈顶,“*”标识为栈顶,有:
lua_remove(L, -3) --> 10 20 40 50*
下面是一个例子,栈的初始状态为10 20 30 40 50 *(从栈底到栈顶,“*”标识为栈顶,有:
lua_settop(L, -3) --> 10 20 30 *
lua_settop(L, 6) --> 10 20 30 nil nil nil *
5、lua_replace
void lua_replace (lua_State* L, int index);
Lua_replace将栈顶元素压入指定位置而不移动任何元素(因此指定位置的元素的值被替换)。
下面是一个例子,栈的初始状态为10 20 30 40 50 *(从栈底到栈顶,“*”标识为栈顶,有:
lua_replace(L, 2) --> 10 50 30 40 * //把50替换到索引的位置,同时去掉栈顶元素
(3)C中加载lua时一些函数的用法
lua_getgobal ------void lua_getglobal (lua_State *L, const char *name);把全局的name的值压到栈顶。
lua_is***(lua_State *L,int index) 检查变量是不是某个类型,index指示变量的顺序,栈顶为-1。
lua_to***(lua_State *L,int index) 获取栈中的变量,然后转换为某个指定的类型,并返回。
lua_close() 销毁所有在指定的Lua State上的所有对象,同时释放所有该State使用的动态分配的空间。
- 『Game』lua和c/c++互相调用实例分析
- lua和c/c++互相调用实例分析(转)
- lua和c/c++互相调用实例分析
- lua和c/c++互相调用实例分析
- lua和c/c++互相调用实例分析
- lua和c/c++互相调用实例分析
- lua和c/c++互相调用实例分析-修正
- lua和c/c++互相调用实例分析
- lua和c/c++互相调用实例分析
- lua和c/c++互相调用实例分析
- C和lua的互相调用
- Lua和C的互相调用
- C和lua的互相调用
- c和lua之间互相调用方法
- Lua编程之Lua和C之间互相调用方式
- lua和c语言互相调用的例子
- 【转】lua和c互相调用的程序示例
- C/C++与Lua互相调用
- sem_wait
- 我的第一天
- 建立web service client
- Max Sum
- Single Number
- 『Game』lua和c/c++互相调用实例分析
- 数据挖掘十大经典算法(7) AdaBoost
- vs2010调用matlab2011;
- CPSR_c是什么
- Java -- Swing 组件使用
- 设计模式:外观模式(7.2)C++版
- ios block一定会范的几个错误
- Git入门学习记录
- 可变参数列表