首页
Web开发
Windows程序
编程语言
数据库
移动开发
系统相关
微信
其他好文
会员
首页
>
其他好文
> 详细
[转]LUA C 互调
时间:
2015-07-20 15:54:30
阅读:
138
评论:
0
收藏:
0
[点我收藏+]
标签:
组件工厂
------3D游戏研发
LUA和C之间的函数调用
1.1 从C程序调用LUA函数
LUA的函数和普通变量一样也是First Class Variable类型,可以看作函数指针变量参与栈操作。因此调用过程分为如下几个步骤:
请求LUA函数(指针)入(GLOBAL)栈。
将函数需要的参数入栈,入栈顺序按照参数被声明的顺序。
告知LUA虚拟机入栈参数的个数、函数返回值的个数,并调用此LUA函数。
从栈定获得返回值,先返回的先入栈,然后将返回值显式出栈。
1.2 从LUA脚本调用C函数
LUA没有提供PYTHON那样丰富的类库,因此复杂的功能需要在C程序中定义好,然后通过lua决定调用时机。在LUA库中定义了可以被LUA虚拟机识别的C函数模型:
int functionName (lua_State* L) {....; return 1;}
这样的函数被是一个合法的lua_CFunction类型,将函数注册到LUA虚拟机中以后,就可以在LUA中以普通LUA函数的方式被调用。注册一个C函数的步骤如下:
声明并定义一个满足上述模型的函数 (eg. myFunInC)
用字符串为此C函数取一个名称并入栈(eg. myFunInLua)
将函数(指针)入栈
调用LUA库的注册函数功能,将上述的名称与函数指针关联
这样就可以在LUA中用myFunInLua()来调用C中的int myFunInC()了
2. 从C调用LUA函数示例
在下面的代码中,我们调用了LUA脚本中的fnEx2函数,返回值从栈中取得,并且要手动出栈。这里,入栈的函数参数会由pcall自动清理。
2.1 LUA测试脚本代码
function
fnex2(str_a, num_b, num_c)
print(str_a);
return num_b
*
100
+
num_c
*
10
,
"
Thank you
"
;
end
;
2.2 VC代码
//
初始化LUA虚拟机
void
InitLuaState(lua_State
*
L)
{
/*
Load Libraries
*/
luaopen_base(L);
luaopen_table(L);
luaL_openlibs(L);
luaopen_string(L);
luaopen_math(L);
}
int
call_lua_function(
void
)
{
const
char
*
szInParam
=
"
This is an [IN] parameter
"
;
const
int
iParam1
=
20
, iParam2
=
50
;
cout
<<
"
=================================
"
<<
endl
<<
"
02_Call_Function
"
<<
endl
<<
"
=================================
"
<<
endl
<<
"
This demo calls functions in LUA scripts.
"
<<
endl
<<
"
Argument 1:
"
<<
szInParam
<<
endl
<<
"
Argument 2:
"
<<
iParam1
<<
endl
<<
"
Argument 3:
"
<<
iParam2
<<
endl
<<
"
---------------------------------
"
<<
endl
<<
"
#OUTPUTS#
"
<<
endl;
lua_State
*
L
=
lua_open();
InitLuaState(L);
int
iError;
/*
Load Script
*/
iError
=
luaL_loadfile(L,
"
../test02.lua
"
);
if
(iError)
{
cout
<<
"
Load script FAILED!
"
<<
lua_tostring(L,
-
1
)
<<
endl;
lua_close(L);
return
1
;
}
/*
Run Script
*/
iError
=
lua_pcall(L,
0
,
0
,
0
);
if
(iError)
{
cout
<<
"
pcall FAILED
"
<<
lua_tostring(L,
-
1
)
<<
iError
<<
endl;
lua_close(L);
return
1; } /* Push a FUNCTION_VAR to STACK */ lua_getglobal(L, "fnex2"); /* Push PARAMETERS to STACK */ lua_pushstring(L, szInParam); lua_pushnumber(L, iParam1); lua_pushnumber(L, iParam2); /* Call FUNCTION in LUA */ iError = lua_pcall( L, //VMachine 3, //Argument Count 2, //Return Value Count 0 ); if (iError) { cout << "pcall FAILED" << lua_tostring(L, -1) << iError << endl; lua_close(L); } /* Check Return Value Types */ if (lua_isstring(L, -1) && lua_isnumber(L, -2)) { cout << "Ret_1(string): " << lua_tostring(L, -1) << endl; cout << "Rec_2(double): " << lua_tonumber(L, -2) << endl; } else { cout << "Wrong Return Values" << endl; } /* POP STACK */ lua_pop(L,2); //只需要清理Return Value,pcall调用的入栈参数会自动清理 lua_close(L); return 0;}
2.3 工具
下面的宏可以简化调用lua函数的代码:
#define
CallLuaFunc(FuncName, Params, Results)
{
lua_getglobal (g_pLuaState, FuncName);
lua_call (g_pLuaState, Params, Results);
}
3. 从LUA调用C函数示例
在下面的例子中,我们注册一个名为rmath的LUA函数,他在C中的函数名为RMath_LUA()
3.1 LUA脚本代码
print (
"
>>> LUA程序开始运行了
"
);
function
fnex3(num_a, num_b)
local
c
=
rmath(num_a, num_b);
print(
"
LUA PRINTTING:
"
, c);
return c;
end
;
3.2 VC程序代码
//
LUA脚本调用C函数
int
call_c_function(
void
)
{
int
iArg1
=
3
, iArg2
=
10
, iError;
cout
<<
"
=================================
"
<<
endl
<<
"
下面的程序演示从LUA脚本中调用C函数
"
<<
endl
<<
"
Argument 1:
"
<<
iArg1
<<
endl
<<
"
Argument 2:
"
<<
iArg2
<<
endl
<<
"
---------------------------------
"
<<
endl
<<
"
#OUTPUTS#
"
<<
endl;
lua_State
*
L
=
lua_open();
InitLuaState(L);
iError
=
luaL_loadfile(L,
"
../test03.lua
"
);
if
(iError) cout
<<
"
载入脚本失败
"
<<
endl;
iError
=
lua_pcall(L,
0
,
0
,
0
);
if
(iError) cout
<<
"
执行LUA脚本失败
"
<<
endl;
/*
将C函数(指针)压栈
*/
lua_pushstring(L,
"
rmath
"
);
lua_pushcfunction(L, RMath_LUA);
lua_settable(L, LUA_GLOBALSINDEX);
/*
LUA函数也是变量(指针),可以压入栈
*/
lua_getglobal(L,
"
fnex3
"
);
/*
将提供给LUA函数的参数入栈
*/
lua_pushnumber(L, iArg1);
lua_pushnumber(L, iArg2);
/*
调用LUA函数(pcall函数会自动清除入栈的变量)
*/
int
Error
=
lua_pcall( L,
//
虚拟机指针
2
,
//
2个参数
1
,
//
1个返回值
0
);
if
(Error) cout
<<
"
pcall调用fnex3函数失败
"
<<
endl;
/*
检验返回值类型
*/
if
(lua_isnumber(L,
-
1
))
{
cout
<<
"
有1个(double)返回值 =
"
<<
lua_tonumber(L,
-
1
)
<< endl; } /* 将LUA函数返回值出栈 */ lua_pop(L, 1); lua_close(L); return 0;}//可供LUA调用的C函数原型int RMath_LUA(lua_State* L){ if (!lua_isnumber(L, 1)) { lua_pushstring(L, "Arg_1不是数字"); lua_error(L); } if (!lua_isnumber(L, 2)) { lua_pushstring(L, "Arg_2不是数字"); lua_error(L); } /* GET ARGUMENT FROM STACK */ double a = lua_tonumber(L, 1); double b = lua_tonumber(L, 2); /* PUSH RESULT TO STACK */ lua_pushnumber(L, a * b); /* COUNT OF RETURN VARS*/ return 1;}
4. 程序解释
4.1 调用LUA脚本中的函数
调用LUA脚本函数主要用到如下几个LUA库函数:
/*
Push a FUNCTION_VAR to STACK
*/
lua_getglobal(L,
"
fnex2
"
);
/*
Push PARAMETERS to STACK
*/
lua_pushstring(L, szInParam);
lua_pushnumber(L, iParam1);
lua_pushnumber(L, iParam2);
/*
Call FUNCTION in LUA
*/
iError
=
lua_pcall( L,
3
,
2
,
0
);
通过lua_getglobal请求函数(指针)入栈,然后将函数参数按声明顺序入栈,调用lua_pcall执行函数。lua_pcall的第一个参数 指向LUA虚拟机,第二个参数表示栈顶有多少个函数参数,第三个参数表示此函数将返回几个值。(pcall自动清理入栈的参数,返回值则需要手动 pop。)
4.2 从LUA调用C函数
主要用到如下几个函数,为求方便您也可以自己定义这样的一个宏。
lua_pushstring(L,
"
rmath
"
);
lua_pushcfunction(L, RMath_LUA);
lua_settable(L, LUA_GLOBALSINDEX);
函数名入栈
lua_CFunction类型的函数指针入栈
调用lua_settable注册函数
这样就可以在lua脚本中调用rmath()函数了。
[转]LUA C 互调
标签:
原文地址:http://www.cnblogs.com/freebird92/p/4661502.html
踩
(
0
)
赞
(
0
)
举报
评论
一句话评论(
0
)
登录后才能评论!
分享档案
更多>
2021年07月29日 (22)
2021年07月28日 (40)
2021年07月27日 (32)
2021年07月26日 (79)
2021年07月23日 (29)
2021年07月22日 (30)
2021年07月21日 (42)
2021年07月20日 (16)
2021年07月19日 (90)
2021年07月16日 (35)
周排行
更多
分布式事务
2021-07-29
OpenStack云平台命令行登录账户
2021-07-29
getLastRowNum()与getLastCellNum()/getPhysicalNumberOfRows()与getPhysicalNumberOfCells()
2021-07-29
【K8s概念】CSI 卷克隆
2021-07-29
vue3.0使用ant-design-vue进行按需加载原来这么简单
2021-07-29
stack栈
2021-07-29
抽奖动画 - 大转盘抽奖
2021-07-29
PPT写作技巧
2021-07-29
003-核心技术-IO模型-NIO-基于NIO群聊示例
2021-07-29
Bootstrap组件2
2021-07-29
友情链接
兰亭集智
国之画
百度统计
站长统计
阿里云
chrome插件
新版天听网
关于我们
-
联系我们
-
留言反馈
© 2014
mamicode.com
版权所有 联系我们:gaon5@hotmail.com
迷上了代码!