zoukankan      html  css  js  c++  java
  • 菜鸟入门之lua与c++相互调用(包括多个demo)

    前两篇文章中,已经介绍了使用vs2010编译lua5.1源代码生成lua.lib 和 vs项目中使用c++调用lua,能够保证demo在vs上执行起来了。

    这里再具体介绍下c++和lua之间的相互调用以及原理。

    c++与lua直接的调用。实际上通过一个栈结构来传递数据,该栈结构栈顶的索引值为-1,向栈底方向索引值依次为-1 ,-2......栈顶索引为1.栈结构里能够放函数。表。字符串。整形等各种lua的基本数据。

    一、在当前cpp文件夹下创建test.lua文件,用于与c++交互调用,代码例如以下:

    print("hello world  from lua file")
    table1 = {}
    table1["dinner"] = "rice"
    table1["hahha"] = "ri123ce"
    gScreenW = 1280;
    function getIntegerSumFuncs(a ,b)
    <span style="white-space:pre">	</span>return a + b
    end
    avg ,sum = average(10 ,20 ,30 ,40 ,50)

    二、先熟悉下lua经常使用的C语言API。

    int luaL_dofile (lua_State *L, const char *filename);//执行lua文件。L是当前已经创建的栈结构。

    返回0,执行文件正常;返回1,代表出现异常。


    void lua_setglobal (lua_State *L, const char *name);//从堆栈上弹出一个值,并将其设到全局变量 name 中

    void lua_getglobal (lua_State *L, const char *name);//把全局变量 name 里的值压入堆栈,栈顶值为-1。

    const char *lua_tostring (lua_State *L, int index);//在栈L的索引值为index处取值并转化成C字符串(lua_tointeger等类似)

    void lua_settop (lua_State *L, int index);//參数同意传入不论什么可接受的索引以及 0。

    它将把堆栈的栈顶设为这个索引。 假设新的栈顶比原来的大。超出部分的新元素将被填为 nil 。

    假设 index 为 0 ,把栈上全部元素移除。

    int lua_gettop (lua_State *L);//返回堆栈上的元素个数(返回 0 表示堆栈为空)

    int lua_next (lua_State *L, int index);从栈上弹出一个 key(键), 然后把索引指定的表中 key-value(健值)对压入堆栈 (指定 key 后面的下一 (next) 对)。 假设表中以无很多其它元素, 那么 lua_next 将返回 0 (什么也不压入堆栈)。

    void lua_pushinteger (lua_State *L, lua_Integer n);//把 n 作为一个数字压栈。


    void lua_close (lua_State *L);//销毁指定 Lua 状态机中的全部对象

    假设须要查询其它函数。推荐到Lua 5.1 參考手冊,非常具体也比較准确。

    三、c++获取lua中的全局字符串。

    //获取lua全局string
    const char* getLuaGlobalString(char *fileName ,char *varName) 
    {
    	lua_State *L = lua_open();
    	luaL_openlibs(L);
    	//载入并执行test.lua文件
    	int isOpen = luaL_dofile(L ,fileName); 
    	if (isOpen == 0) {
    		printf("error loading lua");
    	}
    	//将栈顶的索引设置为该index,假设index传0,移除栈上全部元素
    	lua_settop(L ,0); 
    	//把全局变量 allGlobalChar 里的值压入堆栈。
    	char *allGlobalChar = varName; 
    	lua_getglobal(L ,allGlobalChar); 
    
    	int stateCode = lua_isstring(L ,1); 
    	if (stateCode != 1) {
    		printf("open lua error code:%d" ,stateCode);
    		return NULL;
    	}
    	const char* s = lua_tostring(L ,1);
    	printf("get global screenW is:%s 
    " ,s);
    	lua_pop(L ,1);
    	lua_close(L);
    	return s;
    }
    调用代码:

    getLuaGlobalString("test.lua" ,"gScreenW");

    四、c++获取lua table中的的值

    const char* getLuaVarOfTable(const char *fileName,const char *tableName ,const char *keyName)
    { 
    	lua_State *L = lua_open();
    	luaL_openlibs(L);
    	int isOpen = luaL_dofile(L ,fileName);
    	if (isOpen != 0) 
    	{
    		printf("error open lua file");
    		return NULL;
    	}
    	lua_settop(L ,0);//清空栈
    	lua_getglobal(L ,tableName);
    
    	int stateCode = lua_istable(L ,-1);//取栈顶
    	if (stateCode != 1) 
    	{
    		printf("get table failed code:%d" ,stateCode);
    		return NULL;
    	}
    	lua_pushstring(L ,keyName);
    	lua_gettable(L ,-2); //取栈顶下一个元素
    	const char* valueStr = lua_tostring(L ,-1); //取栈顶
    	printf("get lua table key-value %s-%s" ,keyName ,valueStr);
    	lua_pop(L ,-1);
    	return valueStr;
    }
    调用代码:

    getLuaVarOfTable("test.lua" ,"table1" ,"dinner");

    五、c++获取获取lua中的表

    <pre name="code" class="java">string getLuaVarTable(const char* fileName ,const char *tableName ,char *result)
    {
    	lua_State *L = lua_open();
    	luaL_openlibs(L);
    	int isOpen = luaL_dofile(L ,fileName);
    	if (isOpen != 0) 
    	{
    		printf("error open lua file");
    		return NULL;
    	}
    	lua_getglobal(L ,tableName);
    	int size = lua_gettop(L);
    	lua_pushnil(L);
    	int index = 0;
    	while(lua_next(L ,size))
    	{
    		const char* key = lua_tostring(L ,-2);//取栈顶下一个元素
    		const char* value = lua_tostring(L , -1); //取栈顶
    		//使用memcpy ,index记录地址游标
    		memcpy(&result[index] ,key ,strlen(key));
    		index += strlen(key);
    		//由于sizeof取字符串。最后会有"/0"占一个字节,所以应该减去1
    		memcpy(&result[index] ,"-" ,sizeof("-") - 1);
    		index += 1;
    
    		memcpy(&result[index] ,value ,strlen(value));
    		index += strlen(value);
    		lua_pop(L ,1);
    	}
    	result[index] = 0;
    	cout <<"result is " << result << endl;
    	//free(result);
    	//printf("---%s" ,result.c_str);
    	lua_pop(L ,1);
    	return result;
    }
    
    调用代码:
    

    char* reslut = (char*)malloc(100 * sizeof(char));
    	getLuaVarTable("test.lua" ,"table1" ,reslut);
    	free(reslut);

    六、cpp调用lua中的函数

    //要调用一个函数请遵循下面协议: 首先,要调用的函数应该被压入堆栈。
    //	接着。把须要传递给这个函数的參数按正序压栈。 这是指第一个參数首先压栈。 
    //	最后调用一下 lua_call。 nargs 是你压入堆栈的參数个数。 
    //	当函数调用完成后,全部的參数以及函数本身都会出栈。

    而函数的返回值这时则被压入堆栈。 // 返回值的个数将被调整为 nresults 个, 除非 nresults 被设置成 LUA_MULTRET。

    // 在这样的情况下,全部的返回值都被压入堆栈中。 Lua 会保证返回值都放入栈空间中。 // 函数返回值将按正序压栈(第一个返回值首先压栈), 因此在调用结束后,最后一个返回值将被放在栈顶。

    const char* callLuaFunc(const char* fileName ,const char* functionName) { lua_State *L = lua_open(); luaL_openlibs(L); int isOpen = luaL_dofile(L ,fileName); if (isOpen != 0) { printf("error open lua file %s" ,fileName); return NULL; } lua_getglobal(L ,functionName);//假设表和函数重名,会怎么样 lua_pushinteger(L ,12); lua_pushinteger(L ,3); //第一个參数:函数的个数 第二个參数:函数的返回值个数 lua_call(L ,2 ,1); int result = lua_tointeger(L ,-1); printf("call lua func result : %d" ,result); return NULL; }

    调用代码:

    callLuaFunc("test.lua" ,"getIntegerSumFuncs");

    七、lua调用cpp函数计算平均值

    //cpp计算平均值的函数
    int average(lua_State* L) 
    {
    	int n = lua_gettop(L);
    	double sum = 0;
    	int i;
    	for (i = 1; i <= n; i ++)
    	{
    		if (!lua_isnumber(L ,i)) 
    		{
    			lua_pushstring(L ,"incorrect argument to avg");
    			lua_error(L);
    		}
    		sum += lua_tonumber(L ,i);
    	}
    	lua_pushnumber(L ,sum / n);
    	lua_pushnumber(L ,sum);
    	//这里一定要返回元素个数,若返回0则找不到结果
    	return 2;
    }
    
    //lua调用cpp计算平均值。调用入口
    int averageMain() 
    {
    	lua_State* L = lua_open();
    	luaL_openlibs(L);
    	//注冊lua函数。实际上是将average push到栈结构,然后set average函数为global函数
    	lua_register(L ,"average" ,average);
    	//执行脚本
    	luaL_dofile(L ,"test.lua");
    
    	//把全局变量 avg 里的值压入堆栈
    	lua_getglobal(L ,"avg");
    	// 栈顶是-1,栈底是1
    	cout << "cpp show: avg is " << lua_tointeger(L ,-1) <<endl;
    
    	//从栈中弹出一个元素
    	//lua_pop(L ,1);
    
    	//把全局变量 sum 里的值压入堆栈
    	lua_getglobal(L ,"sum");
    	cout << "cpp show: sum is " << lua_tointeger(L ,-1) <<endl;
    
    	//清除栈结构
    	lua_close(L);
    	return 0;
    }
    
    代码调用:
    averageMain();


    以上是c++和lua调用经常使用的demo。

    这里附上project实例下载地址: http://download.csdn.net/detail/wangbin_jxust/7809743

    假设须要执行该project,须要依照使用vs2010编译lua5.1源代码生成lua.lib 配置一遍,然再执行。








  • 相关阅读:
    HDU
    HDU
    HDU
    CodeForces
    还没有过的题目记录
    HDU
    FZU
    排序:根据数组里某个对象排序
    获取当前毫秒数
    选择日期默认月初到月末
  • 原文地址:https://www.cnblogs.com/wgwyanfs/p/6853487.html
Copyright © 2011-2022 走看看