前两个星期跳槽到了一家游戏公司,做游戏一直是我的梦想。现在终于在毕业三年后,正式开始为了自己的梦想而努力。
由于之前从事的是交通行业,做游戏服务端开发需要的很多技术以前都没怎么接触过,在重新找工之前恶补了一下lua脚本语言。公司这边C++与lua之间的交互用的是lua_tinker来实现的。lua是用C语言写的,lua_tinker也是用C++对lua api的封装。soga..现在终于体会到之前读书的时候为啥总是听说“学会了C/C++语言,以后再接触其他语言比较容易”的含义了。
废话不多说,直接进入正题。源代码下载地址http://download.csdn.net/detail/linjiang275773682/4070469 高丽棒子代码写的十分简洁,一个.h一个.cpp 5个例子。
(一)环境配置
环境配置,首先你需要搭建一个可以用lua的开发环境,这里网上有很多,我就不多说了。然后再将lua_tinker的lua_tinker.h和lua_tinker.cpp添加到你的工程中就可以了。
但是我在配置的时候碰到个问题就是我在google下的lua最新版,在编译的时候总是会报各种错误。无奈直接在公司的svn上拿了目前游戏服务端用的老版本的lua库和头文件,居然就神奇的可以用了。
(二)lua_tinker代码分析(sample1)
我们用棒子提供的sample1来对lua_tinker进行一下初体验。
sample1.lua代码如下:
--lua调用C++函数
result = cpp_func(1, 2)
print("cpp_func(1,2) = "..result)
-- C++调用lua函数
function lua_func(arg1, arg2)
return arg1 + arg2
end
main函数的软代码如下:
// lua_test.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
extern "C"
{
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
};
#include "lua_tinker.h"
int cpp_func(int arg1, int arg2)
{
return arg1 + arg2;
}
int _tmain(int argc, _TCHAR* argv[])
{
lua_State* L = lua_open(); //初始化Lua
luaopen_base(L); //初始化lua基本库
lua_tinker::def(L, "cpp_func", cpp_func); //在L栈中注册C++函数
lua_tinker::dofile(L, "sample1.lua"); //加载lua文件
int result = lua_tinker::call<int>(L, "lua_func", 3, 4); //调用lua中的function lua_func
printf("lua_func(3,4) = %d\n", result); //返回lua的执行结果
lua_close(L); //关闭L
system("PAUSE");
return 0;
}
下面我们用调试模式对lua_tinker的代码进行一下分析
lua_State* L = lua_open(); //初始化Lua
luaopen_base(L); //初始化lua基本库
lua_tinker::def(L, "cpp_func", cpp_func);//在L栈中注册C++函数
分析:
-------------------------------------------------------------------------------------------------------------------
template<typename F> //模板函数
void def(lua_State* L, const char* name, F func)
{
lua_pushstring(L, name); //cpp_func压栈
lua_pushlightuserdata(L, (void*)func); //userdata传入函数指针
push_functor(L, func); //cpp_func=function cpp_func ...end
lua_settable(L, LUA_GLOBALSINDEX); //LUA_GLOBLSINDEX表示在全局表中设置
}
-------------------------------------------------------------------------------------------------------------------
lua_tinker::dofile(L, "sample1.lua"); //加载lua文件
int result = lua_tinker::call<int>(L, "lua_func", 3, 4); //调用lua中的function lua_func
分析:
--------------------------------------------------------------------------------------------------------------------
template<typename RVal, typename T1, typename T2>//模板函数,棒子模板用的真实牛逼
RVal call(lua_State* L, const char* name, T1 arg1, T2 arg2) //call(L,luafunc,3,4)
{
lua_pushcclosure(L, on_error, 0);
int errfunc = lua_gettop(L); //错误处理
lua_pushstring(L, name); //name=luafunc入栈
lua_gettable(L, LUA_GLOBALSINDEX); //取全局表
//lua_pushstring,lua_gettable合起来的作用是取lua_func的实际值,即为函数lua_func
//这两句话组合起来就是lua_getglobal(L,name)
if(lua_isfunction(L,-1)) //判断 luafunc在sample1.lua中是不是函数
{
push(L, arg1); //压栈参数3
push(L, arg2); //压栈参数4 此时栈到栈顶一次是 luafunc 3 4
if(lua_pcall(L, 2, 1, errfunc) != 0) //调用samle1.lua函数luafucn 两个参数,一个返回值
{
lua_pop(L, 1); //出错的话,清栈
}
}
else
{
print_error(L, "lua_tinker::call() attempt to call global `%s' (not a function)", name);
}
lua_remove(L, -2); //移除从栈顶数第二个元素
return pop<RVal>(L); //pop函数中包括了一个lua_tonumber(L,-1)去栈顶结果
}
----------------------------------------------------------------------------------------------------------------------
printf("lua_func(3,4) = %d\n", result);//返回lua的执行结果
lua_close(L); //关闭L
system("PAUSE");
return 0;
}
结束。