【超实用】C++访问Lua中类的成员函数

前言

c++访问lua中的全局函数,网上资料较多,这里不再赘述。但是,c++访问lua中类的成员函数,网上有参考价值的资料很少。访问类的成员函数,有2个关键点:

  1. 导出函数前,要先导出全局table;
  2. 调用函数时,第一个参数要传入self(也就是全局table);

接口封装

要封装一个C++调用Lua类函数的通用接口,需要考虑不定参的问题,所以压入参数部分的代码在调用接口时以匿名函数的形式实现。

  1. 定义一个动态参数入栈的接口
// 定义lua接口封装的传参
struct lua_State;
typedef void (*Action)(lua_State* pLua, va_list ap);
  1. 实现函数主体
/**
 * @brife c++调用Lua类函数通用接口
 * @param strFuncName lua类的成员函数名
 * @param action 执行参数入栈的函数指针
 * @param nArg 入栈参数的个数
 * @param ... 入栈参数(可变)
 */
void CAudioVideoDemoDlg::CallLuaFunc(const std::string strFuncName, Action action, int nArg, ...) 
{ 
	// 先置空一下栈
	lua_settop(m_luaState, 0);
	
	// 获取全局的table,这里zegoSdk为已创建好的全局对象 	
	lua_getglobal(m_luaState, "zegoSdk"); 
	if (!lua_istable(m_luaState, -1)) 
	{ 
		MessageBox(L"lua文件出错,导出sdk失败", L"错误"); 
		return;
	}
	
	// 压入方法名,并获取对于的方法(弹出zegoSdk.strFuncName) 
	lua_pushstring(m_luaState, strFuncName.c_str()); 
	lua_gettable(m_luaState, -2); 
	lua_pushvalue(m_luaState, -2); 
	
	// 压入参数
	if (action != nullptr || action != NULL) 
	{
		va_list ap;
		va_start(ap, nArg); 
		
		action(m_luaState, ap);
		va_end(ap); 
	}

	// 此处要特别注意,需要多传一个self,参数个数要+1
	int iRet = lua_pcall(m_luaState, nArg + 1, 0, 0);
	if (iRet != 0)
	{ 
		// 打印一下调用出错的信息
		std::string strError = strFuncName + ":" + lua_tostring(m_luaState, -1); 
		MessageBoxA(nullptr, strError.data(), "Error", MB_OK); 	
	} 
}

注意:要调用变参相关的函数,需要引用#include

接口调用

  • Lua接口原型
    这里enumScenario为默认参数,调用时可传2个参数。
function M:InitSdk(iAppID, strAppSign, enumScenario)
	-- 获取引擎对象
	M.expressSdk = ZEGO_NS.ZegoExpressLuaSdk:GetInstance()
	
	-- 构造参数
	local zep = ZEGO_NS.ZegoEngineProfile:new()
	zep.appID = iAppID
	zep.appSign = strAppSign
	zep.scenario = enumScenario or Enum_ZegoScenario.ZEGO_SCENARIO_GENERAL
	
	-- 初始化SDK
	M.expressSdk:InitSdk(zep)
end
  • 函数调用
    调用时根据传入参数的类型,做对应解析即可。
CallLuaFunc("InitSdk", [](lua_State* lua, va_list ap){
	// 获取参数
	unsigned int uAppId = va_arg(ap, unsigned int);
	std::string strAppSign = va_arg(ap, char*);
	
	// 将参数压缩到栈中
	lua_pushnumber(lua, uAppId);
	lua_pushstring(lua, strAppSign.data());
	
}, 2, ZEGO_APPID, ZEGO_APPSIGN);

你可能感兴趣的:(Cocos2d-x,Lua基础学习,lua,c++,开发语言)