lua 使用 protocolbuffer

protocolbuffer 简介

protocol buffer是google的一个开源项目,它是用于结构化数据串行化的灵活、高效、自动的方法,例如XML,不过它比xml更小、更快、也更简单。据测试比json还要快很多,你可以定义自己的数据结构,然后使用代码生成器生成的代码来读写这个数据结构。你甚至可以在无需重新部署程序的情况下更新数据结构,具体语法请参考Protocol Buffer使用简介

在lua中使用protocolbuffer

接下来我们进入正题,就是在lua中使用protocolbuffer,为了我让我们的游戏开发更快速,与服务器交互更方便,我们将在游戏lua脚本中使用protocolbuffer,但是google的protocolbuffer原生项目并不支持lua,但是我们有更多的牛人帮我实现了相关的支持,protoc-gen-lua是一个开源项目,这个是下载地址;下面就介绍怎么来使用protoc-gen-lua让我们的lua程序来使用pb。

1.安装

首先要配置环境,要安装python2.7下载地址:https://www.python.org/downloads/release/python-2713/

然后安装protocolbuffer 2.6 for  python下载地址:https://github.com/google/protobuf/releases具体的方法在此就不细说了

2.使用protoc-gen-lua

protoc-gen-lua目录下面有个plugin目录protoc-gen-lua和plugin_pb2.py是用来生成protocol的lua文件的

在win32下面:

先编写一个protoc-gen-lua.bat文件里面写上@python “%~dp0protoc-gen-lua”

我们可以 protoc.exe –lua_out=./ –plugin=protoc-gen-lua=”protoc-gen-lua.bat” PublicStruct.proto 命令来生成

在linux下面:

添加一个硬连 l protoc-gen-lua in your $PATH:

$cd /usr/local/bin && sudo ln -s /path/to/protoc-gen-lua/plugin/protoc-gen-lua

然后使用如下命令:

protoc --lua_out=./ PublicStruct.proto

生成PublicStruct_pb.lua的文件就是我们需要的

3.简单示例

你有一个protoc文件是这样的

person.proto :

[lua]
message Person {
required int32 id = 1;
required string name = 2;
optional string email = 3;
}
[/lua]

编译生成person_pb.lua 文件
然后在我们的lua工程中包含 protobuf 和c/c++工程中包含pb.c
在lua中使用我们的person_pb文件

 

[lua]
require "person_pb"

— Serialize Example
local msg = person_pb.Person()
msg.id = 100
msg.name = "foo"
msg.email = "bar"
local pb_data = msg:SerializeToString()

— Parse Example
local msg = person_pb.Person()
msg:ParseFromString(pb_data)
print(msg.id, msg.name, msg.email)
[/lua]

好了就这么多了

 

 

lua debug.sethook 使用

debug.getinfo简介

因为debug.sethook和debug.getinfo一般都是组合起来使用的,在使用之前我们先来介绍一下debug.getinfo

getinfo(optional thread, function or stack level, optional flag):

该函数返回有关功能的信息表。可以直接给该函数,或者可以给一个号码作为函数的值,这意味着该函数在给定线程的调用堆栈的水平仪功能运行:0级是当前功能(程序getinfo本身); 1级是所谓getInfo函数等等。如果函数比当前功能的数大一些,然后getinfo返回nil。下面一段代码:

[lua]
local funcInfo = debug.getinfo(1)
for k,v in pairs(funcInfo) do
print("key:"..tostring(k).."——value:"..tostring(v))
end

[/lua]

输出:
key:nups——value:0
key:what——value:main
key:func——value:function: 0074BCF0
key:lastlinedefined——value:0
key:source——value:@test_commad.lua
key:currentline——value:1
key:namewhat——value:
key:linedefined——value:0
key:short_src——value:test_commad.lua

返回信息表的字段含义是:

  1. source:标明函数被定义的地方。如果函数在一个字符串内被定义(通过loadstring),source就是那个字符串。如果函数在一个文件中定义,source是@加上文件名。
  2. short_src:source的简短版本(最多60个字符),记录一些有用的错误信息。
  3. linedefined,source中函数被定义之处的行号。
  4. what:标明函数类型。如果foo是一个普通得Lua函数,结果为 “Lua”;如果是一个C函数,结果为 “C”;如果是一个Lua的主chunk,结果为 “main”。
  5. name:函数的合理名称。
  6. namewhat:上一个字段代表的含义。这个字段的取值可能为:W”global”、”local”、”method”、”field”,或者 “”(空字符串)。空字符串意味着Lua没有找到这个函数名。
  7. nups:函数的upvalues的个数。
  8. func:函数本身
  9. currentline:当前函数行号

这个函数的效率比较低,所以尽量使用时只获取我们需要的字段,我们可以通过第二个参数来控制

  • ‘n’    selects fields name and namewhat
  • ‘f’    selects field func
  • ‘S’    selects fields source, short_src, what, and linedefined
  • ‘l’    selects field currentline
  • ‘u’    selects field nup

这个参数是字符串,每一个字母代表一种类型的信息,可以组合在一起使用列如:

[lua]
local funcInfo = debug.getinfo(1,"fl")
for k,v in pairs(funcInfo) do
print("key:"..tostring(k).."——value:"..tostring(v))
end
[/lua]

输出:
key:currentline——value:1
key:func——value:function: 0059BD10

下面我们研究debug.sethook

debug.sethook的使用

而debug.sethook在lua程序设计一书中是这样描述的:debug库的hook是这样一种机制:注册一个函数,用来在程序运行中某一事件到达时被调用。有四种可以触发一个hook的事件:当Lua调用一个函数的时候call事件发生;每次函数返回的时候,return事件发生;Lua开始执行代码的新行时候,line事件发生;运行指定数目的指令之后,count事件发 生。Lua使用单个参数调用hooks,参数为一个描述产生调用的事件:”call”、”return”、”line” 或 “count”。另外,对于line事件,还可以传递第二个参数:新行号。我们在一个hook内总是可以使用debug.getinfo获取更多的信息。

使用带有两个或者三个参数的debug.sethook 函数来注册一个hook:第一个参数是hook函数;第二个参数是一个描述我们打算监控的事件的字符串;可选的第三个参数是一个数字,描述我们打算获取count事件的频率。为了监控call、return和line事件,可以将他们的第一个字母(’c’、’r’ 或 ‘l’)组合成一个mask字符串即可。要想关掉hooks,只需要不带参数地调用sethook即可

[lua]
function trace (event, line)
local s = debug.getinfo(2).short_src
print(s .. ":" .. line)
end
debug.sethook(trace, "l")
print("hi")
[/lua]

输出:
test_commad.lua:8
hi

我们注册一个trace函数来监听执行新行的事件,当print(“hi”)执行时就会触发trace函数打印出print的行号,如果是简体call或者是return没有第二参数的

利用这个特性我们监控任何一个函数的执行情况

[lua]
local funcTab= {}
function testf(event,exarg)
–print("event—->"..event)
local func = debug.getinfo(2).func
if funcTab[func] then
funcTab[func].callcount = funcTab[func].callcount +1
end
end

function myfunction ()
print()
return 10
end
funcTab[myfunction] = {}
funcTab[myfunction]["name"] = "myfunction"
funcTab[myfunction]["callcount"] = 0
debug.sethook(testf,"c")–注册hook
myfunction()
myfunction()
debug.sethook(nil)–关闭hook
for k,v in pairs(funcTab) do
print(v.name)
print(v.callcount)
end
[/lua]

输出:
myfunction
2

表示myfunction被执行了两次

funcTab是用来记录我们要监视的函数的列表,利用这个特性,我们很容易就扩展出一个profiler工具,代码就不解释了。

cocos2d-x 3.7 实现图片按钮 过滤点击透明区域 在lua中使用

首先在widget头文件添加:
[cpp]
virtual bool AlphaTouchCheck(const Vec2 &point);
virtual bool getAlphaTouchEnable();
virtual void setAlphaTouchEnable(bool isAlphaTouch);
bool _isAlphaTouchEnable = true;
[/cpp]
在widget cpp文件中简单实现
[cpp]
bool Widget::AlphaTouchCheck(const Vec2 &point)
{
return true;
}

bool Widget::getAlphaTouchEnable()
{
return _isAlphaTouchEnable;
}

void Widget::setAlphaTouchEnable(bool isAlphaTouch)
{
_isAlphaTouchEnable = isAlphaTouch;
}
[/cpp]
widget中的判断先默认返回true

把开启的开关放在widget中,方便以后layout 和 imageview的不规则点击。开关默认关闭

接下来就是imageview中重载AlphaTouchCheck 函数
[cpp]
bool ImageView::AlphaTouchCheck(const Vec2& point)
{
if (getAlphaTouchEnable())
{
Image* normalImage = new Image();
normalImage->initWithImageFile(_normalImageString);
auto data = normalImage->getData();
if (data == NULL)
{
return true;
}
auto locationInNode = this->convertToNodeSpace(point);
//图片的0,0 是左上角 所以要和触摸点的Y转换一下 也就是“(normalImage->getHeight() – (int)(locationInNode.y) – 1)”
//该data值是把二维数组展开成一个一维数组, 因为每个像素值由RGBA组成, 所以每隔4个char为一个RGBA, 并且像素以横向排列
int pa = 4 * ((normalImage->getHeight() – (int)(locationInNode.y) – 1) * normalImage->getWidth() + (int)(locationInNode.x)) + 3;
unsigned int ap = data[pa];
if (ap < 20)
{
CC_SAFE_DELETE(normalImage);
return false;
}
else
{
CC_SAFE_DELETE(normalImage);
return true;
}
}
return true;
}
[/cpp]

std::string _normalImageString 是记录创建时候的图片名。

编译工程
接下来在lua中使用
[lua]
imageButton:addTouchEventListener(function(sender, type)
if type == ccui.TouchEventType.began then
self.beginPos = gFun.scene.getMousePos();
self.effect = true;
if imageButton:AlphaTouchCheck(gFun.scene.getMousePos()) then –传入鼠标点击位置
imageButton:setScale(0.95);
end
elseif type == ccui.TouchEventType.moved then
if getDistance(self.beginPos, gFun.scene.getMousePos()) > 20 then –判断是不是有滑动
self.effect = false;
end
elseif type == ccui.TouchEventType.canceled then

imageButton:setScale(1);
elseif type == ccui.TouchEventType.ended then
if not self.effect then return end

imageButton:setScale(1);
if imageButton:AlphaTouchCheck(gFun.scene.getMousePos()) then –传入鼠标点击位置
–do something;
end
end
end
)

[/lua]

让syntaxhighlighter 插件支持lua语言

wordpress 的代码高亮插件syntaxhighlighter是不支持lua脚本语言的,这个让读者看起lua代码来着实费劲,我抽空看了一下,只要扩展 syntaxhighlighter里面的shBrush 就好了,先贴出shBrushLua.js的代码
[js]
/**
* SyntaxHighlighter
* http://alexgorbatchev.com/SyntaxHighlighter
*
* SyntaxHighlighter is donationware. If you are using it, please donate.
* http://alexgorbatchev.com/SyntaxHighlighter/donate.html
*
* @version
* 3.0.83 (July 02 2010)
*
* @copyright
* Copyright (C) 2004-2010 Alex Gorbatchev.
*
* @license
* Dual licensed under the MIT and GPL licenses.
*/
;(function()
{
// CommonJS
typeof(require) != ‘undefined’ ? SyntaxHighlighter = require(‘shCore’).SyntaxHighlighter : null;

function Brush()
{
// maker is IkPil, Choi
// http://www.ikpil.com

var keywords = ‘and break do else elseif end false for function if in ‘ +
‘local nil not or repeat return then true until while’;

var functions = ‘_G _VERSION assert collectgarbage dofile error getfenv ‘ +
‘getmetatable ipairs load module next pairs pcall print ‘ +
‘ rawequal rawget rawset require select setfenv setmetatable ‘ +
‘tonumber tostring type unpack xpcall ‘ +
‘coroutine.create coroutine.resume coroutine.running ‘ +
‘coroutine.status coroutine.wrap coroutine.yield ‘ +
‘debug.debug debug.getfenv debug.gethook debug.getinfo ‘ +
‘debug.getlocal debug.getmetatable debug.getregistry ‘ +
‘debug.getupvalue debug.setfenv debug.sethook debug.setlocal ‘ +
‘debug.setmetatable debug.setupvalue debug.traceback ‘ +
‘file:close file:flush file:lines file:read file:seek ‘ +
‘file:setvbuf file:write’ +
‘io.close io.flush io.input io.lines io.open io.output ‘ +
‘io.popen io.read io.stderr io.stdin io.stdout io.tmpfile ‘ +
‘io.type io.write ‘ +
‘math.abs math.acos math.asin math.atan math.atan2 math.ceil ‘ +
‘math.cos math.cosh math.deg math.exp math.floor math.fmod ‘ +
‘math.frexp math.huge math.ldexp math.log math.log10 math.max ‘ +
‘math.min math.modf math.pi math.pow math.rad math.random ‘ +
‘math.randomseed math.sin math.sinh math.sqrt math.tan math.tanh ‘ +
‘os.clock os.date os.difftime os.execute os.exit os.getenv os.remove ‘ +
‘os.rename os.setlocale os.time os.tmpname ‘ +
‘package.cpath package.loaded package.loaders package.loadlib ‘ +
‘package.path package.preload package.seeall ‘ +
‘string.byte string.char string.dump string.find string.format ‘ +
‘string.gmatch string.gsub string.len string.lower string.match ‘ +
‘string.rep string.reverse string.sub string.upper table.concat ‘ +
‘table.insert table.maxn table.remove table.sort’;

this.regexList = [
{ regex: /–.*/gm, css: ‘comments’ }, // one line comments
{ regex: /–\[\[[\S\s]*\]\]/gm, css: ‘comments’ }, // multi line comments
{ regex: SyntaxHighlighter.regexLib.doubleQuotedString, css: ‘string’ }, // strings
{ regex: SyntaxHighlighter.regexLib.singleQuotedString, css: ‘string’ }, // strings
{ regex: SyntaxHighlighter.regexLib.multiLineDoubleQuotedString, css: ‘string’ }, // strings
{ regex: SyntaxHighlighter.regexLib.multiLineSingleQuotedString, css: ‘string’ }, // strings
{ regex: new RegExp(this.getKeywords(keywords), ‘gm’), css: ‘keyword’ }, // keywords
{ regex: new RegExp(this.getKeywords(functions), ‘gm’), css: ‘functions’ } // functions
];
}

Brush.prototype = new SyntaxHighlighter.Highlighter();
Brush.aliases = [‘lua’];

SyntaxHighlighter.brushes.Lua = Brush;

// CommonJS
typeof(exports) != ‘undefined’ ? exports.Brush = Brush : null;
})();
[/js]
接下来就是把shBrushLua.js文件放到scripts 文件夹下面,现在shBrush就准备好了

最后就是修改SyntaxHighlighter插件的php的源码,把shBurshLua添加到shBrush;打开syntaxhighlighter.php文件找到如图位置
clipboard
插入下面一行代码
[php]
wp_register_script( ‘syntaxhighlighter-brush-lua’, plugins_url( $this->shfolder . ‘/scripts/shBrushLua.js’, __FILE__ ), array(‘syntaxhighlighter-core’), $this->agshver );
[/php]
找到$this->brushes = (array) apply_filters( ‘syntaxhighlighter_brushes’, array( 这里在数据组的最下面添加 ‘lua’ => ‘lua’, 如图clipboard2
保存就好了

让我们写段测试代码看一下效果
[lua]
function pirntTest()
for i = 1,10 do
print("hello world")
end
end
[/lua]