您的位置:首页 > 编程语言 > Lua

SLua 绑定 Protobuf-Lua (protoc-gen-lua) 在SLua中使用 Protobuf

2015-11-10 01:37 751 查看
游戏要迁移到Lua,选择了SLua这个开源库来做,SLua很干净,仅仅只提供 Unity 到 Lua 的支持,没有包含其它的库,比如 protoc-gen-lua ,既然没有,那我们就自己把 protoc-gen-lua 编译到 SLua 库中。

1、protoc-gen-lua 的编译安装使用

首先下载 protobuf-2.4.1 编译出 proto工具,然后下载 protoc-gen-lua 进行编译,具体步骤请看
protoc-gen-lua 编译、安装、使用教程

2、下载 slua-0.8.3 下载地址

https://github.com/pangweiwei/slua/releases/tag/v0.8.3

因为我这边用的是 slua-0.8.3 ,但是slua-0.8.3 压缩包里面并没有 编译需要的工程、makefile 文件这些,所以需要从 slua-0.8.5中拷贝过来。

所以再下载 slua-0.8.5
https://github.com/pangweiwei/slua/archive/v0.8.5.zip


把 slua-0.8.5 中的 build 文件夹 拷贝一份到 slua-0.8.3 中。

然后删掉 slua-0.8.5 吧……

如果是直接用 slua-0.8.5 就直接用。

1、编译 SLua Windows 版

打开Vistual Studio 命令提示符,到 slua-0.8.3\build 中执行 make_win_with_2013.bat 。

编译出错


是因为 slua.c 中有错误,打开 slua-0.8.3\Assets\slua_src\slua.c 进行如下修改



再次编译,编译成功。

下面我们把 protoc-gen-lua 的 pb.c 加入编译。

把 protoc-gen-lua-master\protobuf\pb.c 拷贝到 slua-0.8.3\Assets\slua_src 中。

然后修改 slua-0.8.3\Assets\slua_src\msvcbuild.bat ,将 pb.c 加入编译



再次编译,会提示 pb.c 中的一些错误,在上一篇
Luajit 2.0.4 绑定 protoc-gen-lua (Windows 平台)

中都解决了,参考上一篇即可。

修改了pb.c 中的几个错误后,编译成功。

脚本自动把 编译出来的 slua.dll 拷贝到了 slua-0.8.3\slua-0.8.3\Assets\Plugins\x86 和 x64 目录。

下面打开 Unity ,打开slua 中的实例工程。

从上一篇的测试工程中拷贝测试用的 protobuf 文件到 Unity中,注意要放到 SLua 的 存放 lua 文件的 目录中。

然后用SLua 的 Custom 场景做测试,修改下 Custom 的lua代码如下。添加测试Protobuf的代码

require "Person_pb"

MonoBehaviour = UnityEngine.MonoBehaviour
GameObject = UnityEngine.MonoBehaviour

--test Protobuf lua add
local msg = Person_pb.Person()
msg.id = 100
msg.name = "foo"
msg.email = "bar"

local pb_data = msg:SerializeToString()  -- Parse Example

print("create:", msg.id, msg.name, msg.email, pb_data)

local msg1 = Person_pb.Person()
msg1:ParseFromString(pb_data)
print("parser:", msg1.id, msg1.name, msg1.email, pb_data)

--end

function main()

local s,c=Custom.staticCustom();
print(s,c)

local a,b,x=c:instanceCustom()
print(a,b,x)

-- Type parameter can be pass in as string/type table
print(c:getTypeName("UnityEngine.MonoBehaviour,UnityEngine"))
print(c:getTypeName(MonoBehaviour))
print(c:getTypeName(Custom))

-- Test getItem setItem
print("---<"..c:getItem("test"))
c:setItem("test",10)
print("-->"..c:getItem("test"))
c:setItem("a",100)
print("-->"..c:getItem("test"))
end


运行Custom 场景后,会报错。
[string "protobuf"]:31: module 'pb' not found:
no field package.preload['pb']
no file '.\pb.lua'
no file 'D:\Program Files (x86)\Unity4.6.7f1\Editor\lua\pb.lua'
no file 'D:\Program Files (x86)\Unity4.6.7f1\Editor\lua\pb\init.lua'
no file '.\pb.dll'
no file 'D:\Program Files (x86)\Unity4.6.7f1\Editor\pb.dll'
no file 'D:\Program Files (x86)\Unity4.6.7f1\Editor\loadall.dll'
stack traceback:
[C]: in function 'require'
[string "protobuf"]:31: in main chunk
[C]: in function 'require'
[string "Person_pb"]:2: in main chunk
[C]: in function 'require'
[string "custom"]:1: in main chunk
UnityEngine.Debug:LogError(Object)
SLua.LuaState:errorReport(IntPtr) (at Assets/Slua/Script/LuaState.cs:606)
LuaInterface.LuaDLL:lua_pcall(IntPtr, Int32, Int32, Int32)
SLua.LuaState:doBuffer(Byte[], String, Object&) (at Assets/Slua/Script/LuaState.cs:770)
SLua.LuaState:doFile(String) (at Assets/Slua/Script/LuaState.cs:759)
SLua.LuaSvr:start(String) (at Assets/Slua/Script/LuaSvr.cs:86)
Custom:Start() (at Assets/Slua/example/Custom.cs:20)
提示 pb 不存在,就是说 Protobuf 的库没有加载到嘛。

为什么没有加载到?

因为我们本来就没有去加载……

下面来加载

在 slua.c 最后添加函数,加载 Protobuf 的库
//lua protobuf
LUA_API void luaS_openepb(lua_State *L)
{
luaopen_pb(L); //加载pb;
}
然后重新编译slua

然后要在C# 中去调用这个添加的函数

首先修改 LuaDLLWrapper.cs ,添加 接口

namespace LuaInterface
{
using System;
using System.Runtime.InteropServices;
using System.Reflection;
using System.Collections;
using System.Text;
using System.Security;

/**     Modify Record:

lua_xmove:        return void
//lua_gc:           LuaDLLWrapper: enum->int。

lua_objlen:     lua 5.1:  luaS_objlen size_t->int
lua_rawlen:        lua 5.3:  luaS_rawlen size_t->int

lua_setmetatable: lua 5.1 return int
lua 5.3 return void

//lua_type:         LuaDLLWrapper:  return int->enum
lua_isnumber:    LuaDLLWrapper: return bool->int
lua_isstring:      LuaDLLWrapper: return bool->int
lua_iscfunction:   LuaDLLWrapper: return bool->int

lua_call:          5.1 return int->void

lua_toboolean:     LuaDLLWrapper:   return bool->int

lua_atpanic:       return void->intptr

lua_pushboolean:   LuaDLLWrapper: bool ->int
lua_pushlstring:   LuaDLLWrapper: luaS_pushlstring. size_t->int

luaL_getmetafield:  LuaDLLWrapper: return bool->int
luaL_loadbuffe:     LuaDLLWrapper  luaLS_loadbuffer  size_t  CharSet

lua_error:         return void->int
lua_checkstack:  LuaDLLWrapper return bool->int

**/

public class LuaDLLWrapper
{

#if UNITY_IPHONE && !UNITY_EDITOR
const string LUADLL = "__Internal";
#else

const string LUADLL = "slua";
#endif

#if LUA_5_3
[DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl)]
public static extern int luaS_rawlen(IntPtr luaState, int index);
#else
[DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl)]
public static extern int luaS_objlen(IntPtr luaState, int stackPos);
#endif

//[DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl)]
//public static extern int lua_gc(IntPtr luaState, int what, int data);

//[DllImport(LUADLL,CallingConvention=CallingConvention.Cdecl)]
//public static extern int lua_type(IntPtr luaState, int index);

[DllImport(LUADLL,CallingConvention=CallingConvention.Cdecl)]
public static extern int lua_isnumber(IntPtr luaState, int index);

[DllImport(LUADLL,CallingConvention=CallingConvention.Cdecl)]
public static extern int lua_isstring(IntPtr luaState, int index);

[DllImport(LUADLL,CallingConvention=CallingConvention.Cdecl)]
public static extern int lua_iscfunction(IntPtr luaState, int index);

[DllImport(LUADLL,CallingConvention=CallingConvention.Cdecl)]
public static extern int lua_toboolean(IntPtr luaState, int index);

[DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl)]
public static extern void lua_pushboolean(IntPtr luaState, int value);

[DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl)]
public static extern void luaS_pushlstring(IntPtr luaState, byte[] str, int size);

[DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl)]
public static extern int luaL_getmetafield(IntPtr luaState, int stackPos, string field);

[DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl)]
public static extern int luaLS_loadbuffer(IntPtr luaState, byte[] buff, int size, string name);

[DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl)]
public static extern int lua_checkstack(IntPtr luaState, int extra);

//add to openpb
[DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl)]
public static extern void luaS_openepb(IntPtr luaState);
}

}

然户在 LuaState.cs 的

[MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]

static int init(IntPtr L)

这个函数里调用上面添加的函数,修改如下

[MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]
static int init(IntPtr L)
{
LuaDLL.luaL_openlibs(L);

//加载protobuf;
LuaDLLWrapper.luaS_openepb(L);

LuaDLL.lua_pushlightuserdata(L, L);
LuaDLL.lua_setglobal(L, "__main_state");

LuaDLL.lua_pushcfunction(L, print);
LuaDLL.lua_setglobal(L, "print");

LuaDLL.lua_pushcfunction(L, pcall);
LuaDLL.lua_setglobal(L, "pcall");

LuaDLL.lua_pushcfunction(L, import);
LuaDLL.lua_setglobal(L, "import");


运行游戏,输出下面的log,说明成功了。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: