Cocos2d-x中Lua与C++通信


参考文章地址:http://www.himigame.com/lua-game/1343.html



几个Lua中的API介绍


int   luaL_dofile (lua_State *L, const char *filename)  :

加载并运行指定文件,没有错误返回0

void  lua_settop (lua_State *L, int index):

参数允许传入任何可接受的索引以及 0 。 它将把堆栈的栈顶设为这个索引。 如果新的栈顶比原来的大,超出部分的新元素将被填为 nil 。 如果 index 为 0 ,把栈上所有元素移除。

void   lua_getglobal (lua_State *L, const char *name):

把全局变量 name 里的值压入堆栈。

void   lua_pop (lua_State *L, int n):

从堆栈中弹出 n 个元素。相当于清除!

void   lua_pushstring (lua_State *L, const char *s):

把指针 s 指向的以零结尾的字符串压栈。 Lua 对这个字符串做一次内存拷贝(或是复用一个拷贝), 因此 s 处的内存在函数返回后,可以释放掉或是重用于其它用途。 字符串中不能包含有零字符;第一个碰到的零字符会认为是字符串的结束。

更多的API请参考:http://www.codingnow.com/2000/download/lua_manual.html



C++声明


LuaTest.h的代码:
#ifndef __LUA_TEST_H__
#define __LUA_TEST_H__

#include "cocos2d.h"

//引入lua库,由于lua是用C语言实现的,所以需要添加extern "C"
EXTERN_C{
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
}
#include "CCLuaEngine.h"


class LuaTest
{
public:
	/********* 获取Lua中的全局字符串  *********/
	const char* getLuaString(const char* script,const char* varName);
	/********* 获取Lua中全局table的字符串  *********/
	const char* getLuaString4Table(const char* script,const char* table, const char* varName);
	/********* 打印Lua中全局table的元素  *********/
	void printLuaTable(const char* script, const char* table);
	/********* C++调用Lua中的全局函数  *********/
	int callLuaAdd(const char* script, int a,int b);
	/********* Lua调用C++的静态函数  *********/
	void luaCallCppFunctionTest();


	/** 获取文件全路径 **/
	static const char* getFullPath(const char* file);
	/**  C++静态函数需要注册才能被Lua调用,而且参数为一个lua_State*,返回值为int **/
	static int cppAdd(lua_State* L);
};

#endif


C++实现


LuaTest.cpp的代码:
#include "LuaTest.h"

USING_NS_CC;

/********* 获取Lua中的全局字符串  *********/
const char* LuaTest::getLuaString(const char* script,const char* varName){
	lua_State* L = CCLuaEngine::defaultEngine()->getLuaStack()->getLuaState();
	//加载并运行脚本
	int isOpen = luaL_dofile(L, LuaTest::getFullPath(script));
	if (isOpen != 0)
	{
		CCLOG("execute script %s failure. error_code=%d error_msg=%s",script,isOpen,lua_tostring(L,-1));
		return NULL;
	}
	//Lua中的全局字符串varName入栈
	lua_getglobal(L,varName);
	//判断栈顶元素是否字符串
	if(lua_isstring(L,-1)){
		//返回栈顶字符串
		return lua_tostring(L,-1);
	}
	return NULL;
}

/********* 获取Lua中全局table的字符串  *********/
const char* LuaTest::getLuaString4Table(const char* script,const char* table, const char* varName){

	lua_State* L = CCLuaEngine::defaultEngine()->getLuaStack()->getLuaState();
	//加载并运行脚本
	int isOpen = luaL_dofile(L,LuaTest::getFullPath(script));
	if (isOpen != 0)
	{
		CCLOG("execute script %s failure. error_code=%d error_msg=%s",script,isOpen,lua_tostring(L,-1));
		return NULL;

	}
	//对Lua中的table执行压栈
	lua_getglobal(L,table);
	//如果栈顶元素是一个table
	if(lua_istable(L,-1)){
		//key入栈
		lua_pushstring(L,varName);
		//当前栈顶元素为varName,索引为-1;table在varName下面,索引为-2
		//获取table中varName元素的值,第二个参数为当前tabele在栈中的索引位置
		lua_gettable(L,-2);
		//当前栈顶元素为table中varName元素的值
		const char* value = lua_tostring(L,-1);
		//从栈中弹出一个元素
		lua_pop(L,1);
		return value;
	}
	return NULL;
}

/********* 打印Lua中全局table的元素  *********/
void LuaTest::printLuaTable(const char* script, const char* table){
	lua_State* L = CCLuaEngine::defaultEngine()->getLuaStack()->getLuaState();
	//加载并运行脚本
	int isOpen = luaL_dofile(L,LuaTest::getFullPath(script));
	if (isOpen != 0)
	{
		CCLOG("execute script %s failure. error_code=%d error_msg=%s",script,isOpen,lua_tostring(L,-1));
		return;
	}

	//table入栈
	lua_getglobal(L,table);
	//获取栈顶索引(该方法相当于获取栈中元素的个数,因为栈的索引是从1开始往上升的)
	int top = lua_gettop(L);
	//由于lua_next会先对栈执行一次弹出操作,然后再从table中获取一对key-value入栈,所以先放一个nil在栈顶
	lua_pushnil(L);

	if (lua_istable(L,top))
	{
		CCLOG("iterator is start.. table=%s",table);
		//迭代table
		while (lua_next(L,top))	//key出栈,key-value入栈(如果table中还有元素)
		{
			//获取key
			const char* key = lua_tostring(L,-2);
			//获取value
			const char* value = lua_tostring(L,-1);

			CCLOG("%s  -  %s",key,value);

			lua_pop(L,1);//value出栈
		}
		CCLOG("iterator is end..");
		lua_pop(L,1);//key出栈
	}
}

/********* C++调用Lua中的全局函数  *********/
int LuaTest::callLuaAdd(const char* script, int a,int b){
	lua_State* L = CCLuaEngine::defaultEngine()->getLuaStack()->getLuaState();
	//lua函数入栈
	lua_getglobal(L,"add");
	if (lua_isfunction(L,-1))
	{
		//参数入栈
		lua_pushnumber(L,a);
		lua_pushnumber(L,b);
		//调用lua函数:第二个参数是函数的参数个数,第三个参数是函数的返回值个数
		lua_call(L,2,1);
		//获取返回值
		if (lua_isnumber(L,-1))
		{
			return lua_tonumber(L,-1);
		}
	}
	return NULL;
}

/********* Lua调用C++的静态函数  *********/
void LuaTest::luaCallCppFunctionTest(){
	lua_State* L = CCLuaEngine::defaultEngine()->getLuaStack()->getLuaState();
	//注册C++函数(函数必须是静态的)
	lua_register(L,"cppAdd",LuaTest::cppAdd);
	//加载并运行lua脚本
	luaL_dofile(L,LuaTest::getFullPath("script/testCallCppFun.lua"));
}

int add(int a, int b){
	return a+b;
}

/**  C++静态函数 **/
int LuaTest::cppAdd(lua_State* L){
	//从栈中获取参数
	int a = luaL_checknumber(L,-1);
	int b = luaL_checknumber(L,-2);
	//调用C++中的add函数
	int result = add(a,b);
	//对结果入栈
	lua_pushnumber(L,result);
	return 1;//返回值个数
}


const char* LuaTest::getFullPath(const char* file){
	//return CCFileUtils::sharedFileUtils()->fullPathForFilename(file).c_str();
	std::string filePath = CCFileUtils::sharedFileUtils()->fullPathForFilename(file).c_str();
	CCLOG(filePath.c_str());
	return file;
}


Lua代码


test.lua的代码:

--Lua中的字符串
luaStr = "this is a string form lua"

luaTable = { name="linchaolong",age="unknow",sex="man"}

function add(a,b)

	return a+b;
end

testCallCppFun.lua的代码:

result = cppAdd(1,1)
print("call c++ add function result = "..result)



测试代码 


	LuaTest* lua = new LuaTest;

	//获取Lua中的luaStr字符串
	CCLOG("lua string = %s",lua->getLuaString("script/test.lua","luaStr"));
	//获取Lua中table的字符串
	CCLOG("lua table string = %s",lua->getLuaString4Table("script/test.lua","luaTable","name"));
	//打印table中的元素
	lua->printLuaTable("script/test.lua","luaTable");
	//调用lua中的add函数
	lua->callLuaAdd("script/test.lua",1,1);
	//Lua调用C++中的函数
	lua->luaCallCppFunctionTest();

	delete lua;

注意:
1.C++调用Lua函数时,该Lua函数必须是全局的;
2.Lua调用C++函数时,该C++函数必须是静态的;

posted on 2014-07-11 16:06  linchaolong  阅读(346)  评论(0编辑  收藏  举报

导航