cocos2dx lua和c++是如何通信的

2015年02月25日 16:36 0 点赞 0 评论 更新于 2025-11-21 16:26

在游戏开发中,Cocos2d-x 里的 Lua 和 C++ 之间的通信至关重要。本文将聚焦于解决以下几个关键问题,以满足游戏开发中数据通信的需求:

  1. C++ 如何获取 Lua 里面的一个变量值?
  2. C++ 如何获取 Lua 里面一个 Table(Lua 利用 Table 实现面向对象,可调用 Lua 里较高级的引用方法)?
  3. C++ 如何访问 Lua 里面的一个方法?
  4. C++ 如何访问 Lua 里面的一个带参数的方法?
  5. C++ 如何访问 Lua 里面的一个带参数的方法并且带返回值?

实现通信的类库代码

为了实现上述功能,我们定义了一个 C++/Lua 数据通讯类库,以下是具体的代码实现。

PublicSendLuaData.h

//  PublicSendLuaData.cpp
//
//  Lua and C++/C 交互类

#ifndef __PublicSendLuaData__
#define __PublicSendLuaData__

#include "cocos2d.h"
using namespace cocos2d;
using namespace std;

extern "C" {
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
};

class PublicSendLuaData {
public:
// 获取单例实例
static PublicSendLuaData* getInstance();

/*
直接获取 Lua 中的变量名值
@param luaFileName 文件名
@param varName 变量名
*/
const char* getLuaVarString(const char* luaFileName, const char* varName);

/*
获取 Lua 中一个表中的节点名,甚至方法
@param luaFileName 文件名
@param varName 方法名
@param keyName 节点名
*/
const char* getLuaVarOneOfTable(const char* luaFileName, const char* varName, const char* keyName);

/*
调用 Lua 全局 Table
@param luaFileName lua 文件名
@param varName table 变量名
*/
const char* getLuaVarTable(const char* luaFileName, const char* varName);

/*
带参数有返回
@param luaFileName 文件名
@param functionName 方法名
@param arraypar 参数序列
@param arraypartype 参数类型
*/
const char* callLuaFuncParReturn(const char* luaFileName, const char* functionName, CCArray* arraypar, CCArray* arraypartype);

/*
带参数无返回
@param luaFileName 文件名
@param functionName 方法名
@param arraypar 参数序列
@param arraypartype 参数类型
*/
void callLuaFuncPar(const char* luaFileName, const char* functionName, CCArray* arraypar, CCArray* arraypartype);

private:
static bool _isFirst;
static PublicSendLuaData* m_instance;
// 获取文件完整路径
const char* getFileFullPath(const char* fileName);
// 析构函数
~PublicSendLuaData();
};

#endif

PublicSendLuaData.cpp

//  PublicSendLuaData.cpp
//
//  Created by ZISOU-YSJ
//
//  Lua and C++/c 交互类

#include "PublicSendLuaData.h"
#include "CCLuaEngine.h"

PublicSendLuaData* PublicSendLuaData::m_instance = NULL;

// 获取单例实例
PublicSendLuaData* PublicSendLuaData::getInstance() {
if (!m_instance) {
m_instance = new PublicSendLuaData();
}
return m_instance;
}

// 获取变量名值
const char* PublicSendLuaData::getLuaVarString(const char* luaFileName, const char* varName) {
lua_State* ls = CCLuaEngine::defaultEngine()->getLuaStack()->getLuaState();

int isOpen = luaL_dofile(ls, getFileFullPath(luaFileName));
if (isOpen != 0) {
CCLOG("Open Lua Error: %i", isOpen);
return NULL;
}

lua_settop(ls, 0);
lua_getglobal(ls, varName);

int statesCode = lua_isstring(ls, 1);
if (statesCode != 1) {
CCLOG("Open Lua Error: %i", statesCode);
return NULL;
}

const char* str = lua_tostring(ls, 1);
lua_pop(ls, 1);

return str;
}

// 获取 Lua 表中的节点值
const char* PublicSendLuaData::getLuaVarOneOfTable(const char* luaFileName, const char* varName, const char* keyName) {
lua_State* ls = CCLuaEngine::defaultEngine()->getLuaStack()->getLuaState();

int isOpen = luaL_dofile(ls, getFileFullPath(luaFileName));
if (isOpen != 0) {
CCLOG("Open Lua Error: %i", isOpen);
return NULL;
}

lua_getglobal(ls, varName);

int statesCode = lua_istable(ls, -1);
if (statesCode != 1) {
CCLOG("Open Lua Error: %i", statesCode);
return NULL;
}

lua_pushstring(ls, keyName);
lua_gettable(ls, -2);
const char* valueString = lua_tostring(ls, -1);

lua_pop(ls, -1);

return valueString;
}

// 执行 Lua 表,返回表结构
const char* PublicSendLuaData::getLuaVarTable(const char* luaFileName, const char* varName) {
lua_State* ls = CCLuaEngine::defaultEngine()->getLuaStack()->getLuaState();

int isOpen = luaL_dofile(ls, getFileFullPath(luaFileName));
if (isOpen != 0) {
CCLOG("Open Lua Error: %i", isOpen);
return NULL;
}

lua_getglobal(ls, varName);

int it = lua_gettop(ls);
lua_pushnil(ls);

string result = "";

while (lua_next(ls, it)) {
string key = lua_tostring(ls, -2);
string value = lua_tostring(ls, -1);

result = result + key + ":" + value + "\t";

lua_pop(ls, 1);
}
lua_pop(ls, 1);

return result.c_str();
}

// 带参执行 Lua 方法有返回值
const char* PublicSendLuaData::callLuaFuncParReturn(const char* luaFileName, const char* functionName, CCArray* arraypar, CCArray* arraypartype) {
lua_State* ls = CCLuaEngine::defaultEngine()->getLuaStack()->getLuaState();

int isOpen = luaL_dofile(ls, getFileFullPath(luaFileName));
if (isOpen != 0) {
CCLOG("Open Lua Error: %i", isOpen);
return NULL;
}

lua_getglobal(ls, functionName);
int countnum = arraypar->count();
if (countnum > 0) {
for (int i = 0; i < arraypar->count(); i++) {
CCString* typestr = (CCString*)arraypartype->objectAtIndex(i);
CCString* strnr = (CCString*)arraypar->objectAtIndex(i);
if (typestr->isEqual(CCString::create("string"))) {
lua_pushstring(ls, strnr->getCString());
} else if (typestr->isEqual(CCString::create("int"))) {
lua_pushnumber(ls, strnr->intValue());
} else if (typestr->isEqual(CCString::create("bool"))) {
lua_pushboolean(ls, strnr->boolValue());
}
}
}
/*
lua_call
第一个参数: 函数的参数个数
第二个参数: 函数返回值个数
*/
lua_call(ls, countnum, 1);

const char* iResult = lua_tostring(ls, -1);

return iResult;
}

// 带参执行 Lua 方法无返回值
void PublicSendLuaData::callLuaFuncPar(const char* luaFileName, const char* functionName, CCArray* arraypar, CCArray* arraypartype) {
lua_State* ls = CCLuaEngine::defaultEngine()->getLuaStack()->getLuaState();

int isOpen = luaL_dofile(ls, getFileFullPath(luaFileName));
if (isOpen != 0) {
CCLOG("Open Lua Error: %i", isOpen);
}

lua_getglobal(ls, functionName);
int countnum = arraypar->count();
if (countnum > 0) {
for (int i = 0; i < arraypar->count(); i++) {
CCString* typestr = (CCString*)arraypartype->objectAtIndex(i);
CCString* strnr = (CCString*)arraypar->objectAtIndex(i);
if (typestr->isEqual(CCString::create("string"))) {
lua_pushstring(ls, strnr->getCString());
} else if (typestr->isEqual(CCString::create("int"))) {
lua_pushnumber(ls, strnr->intValue());
} else if (typestr->isEqual(CCString::create("bool"))) {
lua_pushboolean(ls, strnr->boolValue());
}
}
}
/*
lua_call
第一个参数: 函数的参数个数
第二个参数: 函数返回值个数
*/
lua_call(ls, countnum, 0);
}

// 获取文件完整路径
const char* PublicSendLuaData::getFileFullPath(const char* fileName) {
return CCFileUtils::sharedFileUtils()->fullPathForFilename(fileName).c_str();
}

// 析构函数
PublicSendLuaData::~PublicSendLuaData() {
CC_SAFE_DELETE(m_instance);
m_instance = NULL;
}

代码调用示例

以上代码中的方法基本能满足在 C++ 中访问 Lua 的各种需求。下面给出一个具体调用 Lua 里带参数全局方法的示例:

CCArray* arraypar = CCArray::create();
arraypar->addObject(CCString::create("参数值"));
CCArray* arraytype = CCArray::create();
arraytype->addObject(CCString::create("string"));
PublicSendLuaData::getInstance()->callLuaFuncPar("Lua文件名", "参数名", arraypar, arraytype);

类型匹配注意事项

在代码中,我们实现了一个类型匹配的方法:

if (typestr->isEqual(CCString::create("string"))) {
lua_pushstring(ls, strnr->getCString());
} else if (typestr->isEqual(CCString::create("int"))) {
lua_pushnumber(ls, strnr->intValue());
} else if (typestr->isEqual(CCString::create("bool"))) {
lua_pushboolean(ls, strnr->boolValue());
}

在使用时,需要注意参数类型的匹配。

Lua 访问 C++ 函数的建议

如果需要在 Lua 中访问 C++ 函数,建议使用 tolua++ 工具类来实现。

通过上述代码和说明,我们详细介绍了 Cocos2d-x 中 C++ 与 Lua 通信的几种常见方式及实现方法,希望能帮助开发者更好地处理游戏开发中的数据通信问题。

作者信息

boke

boke

共发布了 3994 篇文章