Cocos2d-x   发布时间:2022-05-02  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了【COCOS2DX-LUA 脚本开发之十一】C/C++与Lua之间进行数据函数交互以及解决“PANIC: unprotected error in call to Lua API (attempt t大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

使用COcos2d-x 时候,难免需要C/C++调用Lua函数、数据或Lua调用C/C++函数,那么本篇讲详细介绍C/C++与Lua之间的数据、函数交互。

首先让我们来简单了解几个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

了解了以上几个函数,为了方便童鞋们使用,Himi直接贴出封装好的类 HclcData,其中主要包括如下几个功能:

1. C/C++ 调用 Lua 全局变量

2. C/C++ 调用 Lua 全局Table 某元素

3. C/C++ 调用 Lua 全局Table

4. C/C++ 调用 Lua 函数

5. Lua 调用C/C++ 函数

下面直接贴出代码:HclcData.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@H_489_118@ 24
25
26
27
28
29
30
31
32
33
34
35
36
37
@H_618_146@ 38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
@H_450_228@//
@H_450_228@// HclcData.h
@H_450_228@// CppLua
@H_450_228@//
@H_450_228@// Created by Himi on 13-4-17.
@H_450_228@//
@H_450_228@//
@H_944_258@#ifndef __CppLua__HclcData__
@H_944_258@#define __CppLua__HclcData__
@H_944_258@#include "cocos2d.h"
using namespace cocos2d;
using namespace std;
extern "C" {
@H_944_258@#include "lua.h"
@H_944_258@#include "lualib.h"
@H_944_258@#include "lauxlib.h"
};
class HclcData{
public :
@H_489_118@ static HclcData* sharedHD();
@H_450_228@//------------ c++ -> lua ------------//
@H_450_228@/*
@H_450_228@getLuaVarString : 调用lua全局String
@H_450_228@luaFilename = lua文件名
@H_450_228@varName = 所要取Lua中的变量名
@H_450_228@*/
const char * getLuaVarString( const char * luaFilename, const char * varName);
@H_450_228@/*
@H_450_228@getLuaVarOneOfTable : 调用lua全局table中的一个元素
@H_618_146@
@H_450_228@luaFilename = lua文件名
@H_450_228@varName = 所要取Lua中的table变量名
@H_450_228@keyName = 所要取Lua中的table中某一个元素的Key
@H_450_228@*/
const char * getLuaVarOneOfTable( const char * luaFilename, const char * varName, const char * keyName);
@H_450_228@/*
@H_450_228@getLuaVarTable : 调用lua全局table
@H_450_228@luaFilename = lua文件名
@H_450_228@varName = 所要取的table变量名
@H_450_228@(注:返回的是所有的数据,童鞋们可以自己使用Map等处理)
@H_450_228@*/
const char * getLuaVarTable( const char * luaFilename, const char * varName);
@H_450_228@/*
@H_450_228@callLuaFunction : 调用lua函数
@H_450_228@luaFilename = lua文件名
@H_450_228@functionName = 所要调用Lua中的的函数名
@H_450_228@*/
const char * callLuaFunction( const char * luaFilename, const char * functionName);
@H_450_228@//------------ lua -> c++ ------------//
void callCppFunction( const char * luaFileName);
private :
static int cppFunction(lua_State* ls);
static bool _isFirst;
static HclcData* _shared;
const char * getFileFullPath( const char * fileName);
~HclcData();
};
@H_944_258@#endif /* defined(__CppLua__HclcData__) */

HclcData.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@H_489_118@ 24
25
26
27
28
29
30
31
32
33
34
35
36
37
@H_618_146@ 38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
@H_284_874@ 87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
@H_141_944@ 122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
@H_874_998@ 149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
@H_450_228@//
@H_450_228@// HclcData.cpp
@H_450_228@// CppLua
@H_450_228@//
@H_450_228@// Created by Himi on 13-4-17.
@H_450_228@//
@H_450_228@//
@H_944_258@#include "HclcData.h"
@H_944_258@#include "CCLuaENGIne.h"
bool HclcData::_isFirst;
HclcData* HclcData::_shared;
HclcData* HclcData::sharedHD(){
if (!_isFirst){
_shared = new HclcData();
}
return _shared;
}
const char * HclcData::getLuaVarString( const char * luaFilename, const char * varName){
@H_489_118@ 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);
@H_618_146@ return NULL;
}
const char * str = lua_toString(ls,1);
lua_pop(ls,1);
return str;
}
const char * HclcData::getLuaVarOneOfTable( const char * luaFilename, 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;
}
const char * HclcData::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);
@H_284_874@
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();
}
const char * HclcData::callLuaFunction( const char * luaFilename, const char * functionName){
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);
lua_pushString(ls, "Himi" );
lua_pushnumber(ls,23);
lua_pushBoolean(ls, true );
@H_450_228@/*
@H_450_228@lua_call
@H_450_228@第一个参数:函数的参数个数
@H_141_944@ @H_450_228@第二个参数:函数返回值个数
@H_450_228@*/
lua_call(ls,3,1);
const char * iResult = lua_toString(ls,-1);
return iResult;
}
void HclcData::callCppFunction( const char * luaFileName){
lua_State* ls = CCLuaENGIne::defaultENGIne()->getLuaStack()->getLuaState();
@H_450_228@/*
@H_450_228@Lua调用的C++的函数必须是静态的
@H_450_228@*/
lua_register(ls, "cppFunction" ,cppFunction);
int isOpen = luaL_dofile(ls,getFileFullPath(luaFileName));
if (isOpen!=0){
CCLOG( "Open Lua Error: %i" ,isOpen);
return ;
}
}
int HclcData::cppFunction(lua_State* ls){
int luaNum = ( int )lua_tonumber(ls,1);
@H_874_998@ int luaStr = ( int )lua_toString(ls,2);
CCLOG( "Lua调用cpp函数时传来的两个参数: %i %s" ,luaNum,luaStr);
@H_450_228@/*
@H_450_228@返给Lua的值
@H_450_228@*/
lua_pushnumber(ls,321);
lua_pushString(ls, "Himi" );
@H_450_228@/*
@H_450_228@返给Lua值个数
@H_450_228@*/
return 2;
}
const char * HclcData::getFileFullPath( const char * fileName){
return CCFileUtils::sharedFileUtils()->fullPathForFilename(fileName).c_str();
}
HclcData::~HclcData(){
CC_SAFE_deletE(_shared);
_shared=NULL;
}

大家可以直接拿来用的,使用简单,测试如下:

首先C++测试代码:

1
2
3
4
5
6
7
8
9
10
11
12
@H_944_258@#include "HclcData.h"
CCLOG( "Str = %s" ,HclcData::sharedHD()->getLuaVarString( "Test.lua" , "luaStr" ));
CCLOG( "Str2 %s" , "luaStr2" ));
CCLOG( "age = %s" ,HclcData::sharedHD()->getLuaVarOneOfTable( "Test.lua" , "luaTable" , "age" ));
CCLOG( "name = %s" , "name" ));
CCLOG( "sex = %s" , "sex" ));
CCLOG( "Table = %s" ,HclcData::sharedHD()->getLuaVarTable( "Test.lua" , "luaTable" ));
CCLOG( "Call Lua Function BACk: %s" ,HclcData::sharedHD()->callLuaFunction( "Test.lua" , "luaLogString" ));
HclcData::sharedHD()->callCppFunction( "Test.lua" );
HclcData::sharedHD()->callLuaFunction( "Test.lua" , "call_Cpp" );

对应测试的Test.Lua文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
luaStr = "I' m Himi"
luaStr2 = "are you ok!"
luaTable = {age = 23 ,name = "Himi" ,sex = "男" }
function luaLogString(_logStr,_logNum,_logBool)
print ( "Lua 脚本打印从C传来的字符串:" ,_logStr,_logBool)
return "call lua function OK"
end
function call_Cpp(_logStr,_logBool)
num, str = cppFunction( 999 , "I'm a lua String" )
print ( "从cpp函数中获得两个返回值:" ,num, str )
end

运行测试结果如下:

1
2
3
4
5
6
7
8
9
10
Cocos2d: Str = I' m Himi
Cocos2d: Str2 are you ok!
Cocos2d: age = 23
Cocos2d: name = Himi
Cocos2d: sex = 男
Cocos2d: Table = name:Himi age:23 sex:男
Lua 脚本打印从C传来的字符串: Himi 23 true
Cocos2d: Call Lua Function BACk: call lua function OK
Cocos2d: Lua调用cpp函数时传来的两个参数: 999 I'm a lua String
从cpp函数中获得两个返回值: 321 Himi

在Himi做这些交互时出现了如下错误:

1
“PANIC: unprotected error in call to Lua API (attempt to index a nil value)

如下图:

最后Himi发现造成此问题的原因有两种情况

1. 是你的lua文件位置路径!

细心的童鞋应该看到,每次我使用luaL_dofile 函数时传入的都是调用了一个getFileFullPath的函数进行获取文件的完整路径!

在HclcData中包装了一个函数:

1
2
3
const char * HclcData : : getFileFullPath ( const char * filename ) {
return CCFileUtils : : sharedFileUtils ( ) - > fullPathForFilename ( filename ) .c_str ( ) ;
}

2. 如果你是cpp调用lua函数,那么你的这个lua函数不能是local的!

反之,如果你lua调用cpp函数,同理,cpp函数肯定是static的!

另外,如果你cpp调用lua,等同于重新加载了这个lua文件,是不同的对象!因此你应该建立一个新的lua文件,主要用于交互所用!

例如你a.lua中有一个tab的成员变量,那么你使用cpp调用lua函数后,这个tab是新的对象!

最后附上HclcData和Test.lua 下载地址:http://vdisk.weibo.com/s/y0zws

OK,本篇就到这里,有什么问题及时联系Himi!

大佬总结

以上是大佬教程为你收集整理的【COCOS2DX-LUA 脚本开发之十一】C/C++与Lua之间进行数据函数交互以及解决“PANIC: unprotected error in call to Lua API (attempt t全部内容,希望文章能够帮你解决【COCOS2DX-LUA 脚本开发之十一】C/C++与Lua之间进行数据函数交互以及解决“PANIC: unprotected error in call to Lua API (attempt t所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。