前段时间封装了一个意在跨平台,且满足自己需求的很light的LuaEngine,对于表参数和表返回值留了白,想找时间研究一下,近日终于弄好。
首先我对C++的参数和返回值做了一个封装
enum
{
SD_NUMBER=0,//数字类型
SD_STRING,//字符串类型
SD_TABLE,//表
};
structSSDTable
{
intnNum;
void*pValue;
};
//脚本参数对象
structSScriptParamObj
{
intnType;//参数类型,SD_NUMBER或者SD_STRING
unionUScriptParam//参数值
{
intnNumber;//数字
charszString[64];//字符串
SSDTablestTable;
}unValue;
SScriptParamObj()
{
memset(this,0,sizeof(*this));
}
~SScriptParamObj()
{
}
voidoperator=(intnValue)
{
nType=SD_NUMBER;
unValue.nNumber=nValue;
}
voidoperator=(constchar*str)
{
nType=SD_STRING;
unValue.szString[0]=0;
if(str!=NULL)
{
strncpy(unValue.szString,str,sizeof(unValue.szString));
}
}
voidoperator=(SSDTable&pT)
{
nType=SD_TABLE;
unValue.stTable.nNum=pT.nNum;
unValue.stTable.pValue=(void*)pT.pValue;
}
};
需要细心一点的就是,对于嵌套表的处理,不用说大家也就知道了--递归。
下面的这个函数是C++调用Lua的函数,Lua函数的参数和返回值都作为C++的参数
boolCLuaScript::CallFunction(constchar*szFuncName,SScriptParamObj*pIn,
intnInNum,SScriptParamObj*pRet,intnRetNum)
{
if(szFuncName==NULL)
{
returnfalse;
}
assert(m_pManager->GetMasterState());
assert(m_pThreadState);
lua_getglobal(m_pThreadState,szFuncName);
for(inti=0;i<nInNum;i++)
{
//参数的三种类型
switch(pIn[i].nType)
{
caseSD_NUMBER:
lua_pushnumber(m_pThreadState,pIn[i].unValue.nNumber);
break;
caseSD_STRING:
lua_pushstring(m_pThreadState,pIn[i].unValue.szString);
break;
caseSD_TABLE:
//现在栈顶创建一个新的表
lua_newtable(m_pThreadState);
intnSize=pIn[i].unValue.stTable.nNum;
SScriptParamObj*pData=(SScriptParamObj*)pIn[i].unValue.stTable.pValue;
PushTable(pData,nSize);
break;
}
}
intnStatus=lua_pcall(m_pThreadState,nInNum,nRetNum,0);
for(inti=nRetNum-1;i>=0;i--)
{
//参数的三种类型,pop的顺序,完全靠直觉
switch(pRet[i].nType)
{
caseSD_NUMBER:
pRet[i].unValue.nNumber=lua_tonumber(m_pThreadState,-1);
lua_pop(m_pThreadState,1);
break;
caseSD_STRING:
strcpy(pRet[i].unValue.szString,lua_tostring(m_pThreadState,-1));
lua_pop(m_pThreadState,1);
break;
caseSD_TABLE:
ReturnTable(&pRet[i]);
lua_pop(m_pThreadState,1);
break;
}
}
if(nStatus!=0)
{
FormatError();
OutputError("RuntimeError:");
returnfalse;
}
returntrue;
}
处理表作为输入参数,对于嵌套表的处理,请大家详细的看下代码就明白了
voidCLuaScript::PushTable(SScriptParamObj*pIn,intnInNum)
{
for(inti=0;i<nInNum;i++)
{
//参数的三种类型
switch(pIn[i].nType)
{
caseSD_NUMBER:
//添加key和value,下标从1开始
lua_pushnumber(m_pThreadState,i+1);
lua_pushnumber(m_pThreadState,pIn[i].unValue.nNumber);
lua_rawset(m_pThreadState,-3);
break;
caseSD_STRING:
lua_pushnumber(m_pThreadState,i+1);
lua_pushstring(m_pThreadState,pIn[i].unValue.szString);
lua_rawset(m_pThreadState,-3);
break;
caseSD_TABLE:
lua_pushnumber(m_pThreadState,i+1);
lua_newtable(m_pThreadState);
intnSize=pIn[i].unValue.stTable.nNum;
SScriptParamObj*pData=(SScriptParamObj*)pIn[i].unValue.stTable.pValue;
PushTable(pData,nSize);
lua_rawset(m_pThreadState,-3);
break;
}
}
}
表作为结果返回的时候,要注意下面的情况了是否返回表结构的逻辑,程序员应该知道的,如果是 表结构,请务必手动删除分配的内存,而且
在多层的嵌套表结构中,要逐层清理。大概意思就是在引擎中会new内存,而这块内存,引擎并不知道在什么时候释放,需要程序员去手动的释放
voidCLuaScript::ReturnTable(SScriptParamObj*pRet)
{
//获取到表的索引
intnNum=0;
intnIndex=lua_gettop(m_pThreadState);
lua_pushnil(m_pThreadState);
//先得到数组的长度
while(lua_next(m_pThreadState,nIndex)!=0)
{
nNum++;
//移除'value';保留'key'做下一次迭代
lua_pop(m_pThreadState,1);
}
nIndex=lua_gettop(m_pThreadState);
//这时候栈顶还是表
lua_pushnil(m_pThreadState);
SScriptParamObj*pObject=newSScriptParamObj[nNum];
pRet->unValue.stTable.pValue=pObject;
pRet->unValue.stTable.nNum=nNum;
nNum=0;
while(lua_next(m_pThreadState,nIndex)!=0)
{
//'key'(索引-2)和'value'(索引-1)
//只对Value感兴趣
if(lua_type(m_pThreadState,-1)==LUA_TSTRING)
{
pObject[nNum++]=lua_tostring(m_pThreadState,-1);
}
elseif(lua_type(m_pThreadState,-1)==LUA_TNUMBER)
{
pObject[nNum++]=(int)lua_tonumber(m_pThreadState,-1);
}
elseif(lua_type(m_pThreadState,-1)==LUA_TTABLE)
{
ReturnTable(&pObject[nNum++]);
}
else
{
nNum++;
}
//移除'value';保留'key'做下一次迭代
lua_pop(m_pThreadState,1);
}
}
分享到:
相关推荐
进行C++与LUA交互编程,你需要了解以下几个关键概念: - **LUA_CFUNCTION**:C++代码中定义的函数可以注册为LUA的函数,通过`LUA_CFUNCTION`类型标识。这些函数会被LUA调用,参数和返回值都通过LUA栈进行传递。 - ...
在这个项目中,我们看到了一个名为`luaTest.cpp`的文件,这很可能是实现C++与Lua交互的主要代码。`luaTest.cpp`可能包含了初始化Lua环境、加载Lua脚本、调用Lua函数以及从Lua中接收数据的代码。 `stdafx.cpp`和`...
1. **头文件**:例如 `lua.h`、`luac.h` 等,这些头文件定义了 Lua API,供 C/C++ 程序调用 Lua 的函数和结构体,以便在 C 代码中与 Lua 脚本进行交互。 2. **库文件**:`liblua.a` 或 `liblua.so` 是静态和动态...
5. 传递数据:C++与Lua之间可以传递不同类型的数据。使用`lua_pushnumber`、`lua_pushstring`等函数将C++数据推送到Lua栈,使用`lua_tonumber`、`lua_tostring`等函数从Lua栈获取数据。 6. 清理:调用`lua_settop(L...
8. **关闭Lua状态机**:当不再需要与Lua交互时,记得通过`lua_close(L)`释放资源。 以上就是C++与Lua交互的基本流程。在实际项目中,你可能还需要处理更复杂的数据类型转换,如从Lua到C++的对象映射,以及错误处理...
luajava是Lua语言与Java平台的交互库,它允许Lua脚本直接调用Java类和方法,同时也让Java程序能够执行Lua代码,实现了两种语言的无缝集成。这个压缩包"luajava-x32-x64.zip"包含了luajava-1.1.jar的64位和32位版本,...
其次,通过集成LuaplusHelper.h类,新手可以更轻松地开始编写Lua代码,这个类提供了一系列的辅助方法,使得在C++中与Lua交互变得更加直观和简单。 使用"Luaplus-lua5.3-lib",开发者可以快速实现以下功能: 1. **...
在Linux环境中,C++与Lua交互是常见的技术实践,特别是在游戏开发、脚本扩展和自动化任务中。本文将深入探讨如何在C++程序中调用Lua动态链接库,并讲解其编译过程和环境配置。 首先,我们需要理解Lua的动态链接库...
本示例中的"lua_test.rar"文件集是一个关于C++与Lua交互的实践案例,主要探讨了如何通过Lua脚本调用C++编写的函数。下面我们将详细探讨这个主题。 首先,Lua是一种轻量级的脚本语言,它简洁、易学,常被用于游戏...
**标题:“Lua与C++的交互”** 在游戏开发领域,常常需要使用脚本语言来增强游戏的灵活性和可扩展性,Lua就是一种常见的选择。它轻量级、易读易写,适合嵌入到像C++这样的系统编程语言中。本项目重点展示了如何在...
采用cmake构建项目,生成c_shuffle.so C++库提供lua使用,交互内容是lua传递数组...目的:1、方便理解C++ Lua交互方式,通过栈来进行 2、如何生成动态库文件提供lua使用 3、lua复杂运算,可以用C++实现,绑定给lua使用
1. **lua.h**: 这是Lua C API的头文件,定义了所有与C语言交互的函数和数据结构。 2. **lua.c/lua.o**: Lua的主解析器和虚拟机实现,编译后的对象文件或静态库。 3. **lapi.c/lapi.o**: 实现了Lua与C之间的接口,...
当Lua与C++结合时,可以实现快速的原型开发,同时利用C++的强大性能进行底层优化。 在Lua和C++的交互中,通常有两种主要的方式:一是通过C++调用Lua脚本,二是通过Lua调用C++编写的函数。这种方式使得开发者可以在...
这是一组用于与Lua交互的函数,允许C++代码创建和控制Lua虚拟机,读写全局变量,调用 Lua 函数,甚至注册C++函数供Lua调用。在`main.cpp`文件中,我们可能会看到以下关键步骤: 1. 初始化Lua环境: 使用`luaL_new...
解决C++ 工程调取带有socket功能的lua脚本无法调取执行问题,附件为lua socket 源代码,可自行生成lua socket 环境,支持lua5.3 ,详细操作步骤请参考:https://blog.csdn.net/wantedww/article/details/112094145
通过实际的代码示例,你可以了解如何在Lua中进行基本操作,如变量声明、运算符使用、函数定义与调用,以及如何利用表进行数据存储和处理。此外,这个文档可能还会介绍如何使用Lua的元表和元方法来实现面向对象编程,...
当C++不再需要与Lua交互时,记得调用`lua_close()`关闭Lua状态机,释放资源。 示例代码: ```cpp #include <lua.h> #include #include int myCppFunction(lua_State* L) { // C++函数处理逻辑 return 0; // ...
2. **C/C++与Lua交互的库** 在C/C++中调用Lua脚本,我们需要利用Lua提供的C API。Lua的源代码库包含一组C函数,允许我们加载、运行和控制Lua虚拟机。这些API函数提供了创建和操作全局变量、执行脚本、调用函数、...
- **性能优化**:探讨如何在C++与Lua交互过程中进行性能优化,比如减少不必要的栈操作。 - **安全性考虑**:讨论如何安全地在C++中调用Lua脚本,避免潜在的安全漏洞。 - **应用场景**:介绍更多关于C++与Lua结合的...
首先,我们需要了解C++与Lua交互的基础。Lua是一个轻量级的脚本语言,它的设计目标是易于嵌入到其他应用中,而C++则是一种通用的、面向对象的编程语言。为了在C++中调用Lua,我们需要使用Lua的C API,这是一个供C和...