每日遨游知识海洋,择录一些沙石,如碰上珠玉,自然再好不过。
TOOLS
- Xcode 7.x 安装插件管理器
Alcatraz
curl -fsSL https://raw.github.com/supermarin/Alcatraz/master/Scripts/install.sh | sh
然后重启Xcode。
-
gitignore.io网站可以自动生成需要的
.gitignore
文件。 -
OS X EI Capitan(10.11)下,使用cocos2dx的
generator
生成js 或者 lua 绑定的时候会报一个libclang.dylib 找不到的错误(libclangError: dlopen(libclang.dylib,6): image not found.)。这是因为系统SIP的原因。解决办法有三种,一是关闭SIP;二是./frameworks/cocos2d-x/tools/bindings-generator/clang/cindex.py 第 3395 行 改为 : library = cdll.LoadLibrary("../bindings-generator/libclang/" + self.get_filename())
;三是修改generator.py
class Generator(object):
def __init__(self, opts):
libchangPath = os.path.abspath(os.path.join(os.path.dirname(__file__), 'libclang'))
cindex.Config.set_library_path(libchangPath)
self.index = cindex.Index.create()
推荐第二种。为啥?最快最简单啊。
SNIPPET
lua utf8
lua在5.3版中才原生支持utf8,使用之前的版本就只有自己实现。
lua source inside
探寻lua5.2内部实现,质量非常高,言简意赅,相比云风的源码欣赏更适合快速入门。除了博文,作者还有更细致更深入的版本。
作者还有一个分析lua5.1,两相对比,可以看出作者在分析5.2版时更加成熟,更加深入浅出游刃有余。
LANGUAGE
C
- 打印结构体内的成员变量地址,输出的是相对地址(对齐之后的)
- char s1[]与char *s2:
s1
,s2
保存的都是地址,都是指向的内容的首地址,只是恰好数组的地址与其内容首地址相等了。所以,访问 s1 肯定等于 &s1, s2 不一定等于 &s2。其本质原因在于,数组与其内容肯定在同一个地方,内存连续;而指针与其指向的内容不一定内存连续。 - static修饰变量时,表示变量存储于静态区,作用范围为定义之处到当前文件结尾;修饰函数时,表示该函数作用范围限于当前文件。对作用域的限制是为了不让其他文件直接访问,通过地址间接访问是可以的。(C++里的static多个作用,用于表示修饰对象属于类不属于具体对象。)
- const修饰规则:忽略类型名,const修饰最近的值。如const int *p等同于int const *p,修饰的是 *p;而int *const p,修饰的是 p。
- 空结构体的大小是编译器相关的,比如VC6是1,但GCC是0.
Lua
- userdata就是Lua申请的一块原生内存,lightuserdata是一个纯粹的指针
- 如果把Lua虚拟机看成单核CPU的话,协程就类似进程。区别在于,进程调度由CPU负责,协程的调度可以由开发者插手。
- 协程中,resume/yield的返回值就是它们后面对应的一个yield/resume的(额外)参数。协程首次resume启动时,传递的参数是没有yield对应的,所以是协程的参数。协程最后一个resume时,后面没有yield提供返回值,所以协程的返回值就是resume的返回值。
- 协程的优点:让原先需要异步+回调的逻辑可以用看似同步的方式实现。很多需要用传统多线程的地方都可以用协程实现,还不用加锁之类的。
- Lua table中的数组元素会优先使用内部排序,比如
t = {[1] = 1.1, 1}
,a[1]
的值为1,不是1.1。
APP
ios
- 音频后台播放:Xcode7.x,项目属性里选择
Capabilities
,打开Background Modes
,勾选Audio...
。然后在viewDidLoad
函数里加上
//swift
AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
- 代码加载
storyboard
中制作好的ui
let sb = UIStoryboard(name:"Main", bundle: nil)
var musicControlView = sb.instantiateViewControllerWithIdentifier("musicControl") as! MusicViewController
上述Main
指的是待加载storyboard的名字,musicControl
指的是待加载UI的storyboard ID,MusicViewController
指的是待加载UI对应的类名。
其实看函数名也知道需要传什么参数,但是举例说明简单明了。
CONFIG
配置OSX开发环境
-
macosx终端配置:iTerm2 + zsh + on my zsh(agnoster theme) + Powerline Font
-
Emacs配置:在
~
目录下执行命令:git clone https://github.com/keyring/emacs.d.git .emacs.d
-
Emacs 在win8以上版本中文乱码,加上字体设置即可:
(set-fontset-font "fontset-default" 'gb18030 '("Microsoft Yahei" . "unicode-bmp"))
OTHERS
虚拟机
-
动手实现代码虚拟机与逆向被虚拟机所保护的二进制文件相辅相成。让我对脚本的安全很有启发。比如,越来越多的游戏使用lua作为逻辑脚本,那lua代码的编译/反编译,加密/揭秘就很重要了。其中,安全措施一般均为定制lua的vm,然后使用加密算法对定制后的字节码再加密。当然,这些手段都只是增加解密的难度,不可能完全防破解。所以,增加一些lua反编译知识也是好的。
-
可以学习一下lua的vm,了解他的字节码,参考其源码和分析,可以考虑写一个反编译工具,类似luadec,最终定制一个
kvm
和kvmdec
。 -
最简易的定制lua就是修改
lopcodes.h
和lopcodes.c
里面的两个枚举类型(OpCode和luaP_opmodes)里的元素顺序。至于是手动乱序还是用代码乱序就看需求了。然后使用定制的luac编译lua文件,常见的luadec就没法反编译出正确的代码。当然,还是可以通过静/动态分析来找出你的乱序opcode,进而反编译出来。绝对的安全还是有点难。
图形学
- OpenGL绘制效率与OpenGL API直接相关的方面表现在CPU调用API导致的驱动开销和GPU响应API进行绘制的开销。
CPU调用API导致的驱动开销分为三类:
1、驱动提交渲染命令的开销,即调用 OpenGL Draw 函数。
2、驱动提交状态命令导致的状态切换开销,比如片元测试,shader切换,texture切换等等。
3、API调用时加载或同步数据时的开销
针对性的优化方案有:
1、采用合并批次,实例渲染可以降低Draw函数次数
2、对可渲染物进行有效的排序,将状态相同的可渲染物依次渲染,从而降低状态切换
3、API本身与驱动的优化