这个月工作比较紧张,没有系统学习什么新知识。平时会碰到一些半生不熟的东西,因为赶时间,上网查查,问问人,也能将就着用着。但是心里总会有些不踏实,总想着能多明白一层也是好的。
1.lua与c交互时的堆栈
每个lua_state都只有一个堆栈。当lua调用一个c函数时,会保证这个函数可以使用LUA_MINSTACK个(默认是20)堆栈空间,不够的话会自动扩充堆栈。默认情况下,为了效率,lua是不对堆栈操作(例如push)进行越界检查的。但有时打开这种检查功能有助于发现一些隐蔽bug。luaconf.h里有一个宏可以打开这个检查。
使用正负索引对堆栈进行访问时,堆栈的可见范围会被限定在当前函数栈里,即当前函数的栈底base,与堆栈栈顶top之间。这也是我们在注册的lua c函数里,可以用1来索引当前函数调用第一个参数的原因。
注意保持堆栈平衡,错误信息处理完后也要弹出堆栈。
另外lua的面向对象冒号语法,会隐式传递对象本身。在c中实现这种函数时,要注意索引1处的位置是对象本身。
2.c++ static变量的继承、覆盖
其实与普通变量一样,如果在子类里重新定义(覆盖),即重新分配了空间,在子类语境内的读写操作都是针对这个新定义的变量。否则操作的是父类变量。
3.object c特性
a.声明定义和调用时,可以指明参数名称
[myRectangle setOriginX: 30.0 y: 50.0];
也可以不指明
[myRectangle setOrigin:30.0 :50.0];
对阅读调用函数的代码有帮助。
但是这种具名参数,并不支持可选参数、参数顺序可变等特性。指定参数名称的话,第一个参数的名称要和函数名称拼在一起,这点让我感到有些层次混乱。
b.消息机制
[myRectangle setOriginX: 30.0 y: 50.0];
这种函数调用,在object c里被称作向myRectangle对象发送了setOriginX消息。消息是面向对象设计方法里的正式称呼,概念也比较抽象。对象对消息的反应,具体是调用一个成员函数(c++),还是由运行时处理(object c),则视语言而定。运行时(runtime)在object c里是个很重要的概念,虽然c++里也有运行时类型识别(RTTI),但是地位和功能与object c的运行时相比,可能要差上不少。obect c里,每一个消息的发送,都要经过运行时系统。在编译阶段,我们甚至可以发送一个源码里并不存在对应函数方法的消息给对象。我们也可以在运行时动态创建一个源码里并不存在类型、变量、方法等。这种运行时机制在面向对象的语义下提供了更大的灵活性,当然也付出了一些性能上的代价。
c.其他比如接口、分部类等语言特性,与C#都比较接近。
4.object c与c++混编
在我目前的项目里,少部分会使用object c代码,而最常打交道的仍然是c++代码。object c代码以.m为扩展名,c++代码以.cpp为扩展名。两者似乎都是使用LLVM编译器。如果object-c代码里想要包含c++代码(或者说是object-c++代码?),可以把扩展名由.m改为.mm。同时object c语言支持c语言语法。cpp文件里不可包含object c代码。似乎xcode是根据扩展名来选择不同的编译前端来进行编译工作的。
我们项目采用的混编方式是用c语言做封装层。需要调用的object c代码,都提供一个c接口。这种方案的缺点是写wrapper代码很烦人。
http://philjordan.eu/article/strategies-for-using-c++-in-objective-c-projects#ref1
这篇文章的作者介绍了一种比较简便的混编方案。要点是隐藏实现。
5.utf8
unicode规定了字符编码,但没有规定字符编码的存储格式。
utf8、utf16都是具体的存储格式,utf16恰好与unicode编码的直接存储格式基本相同。
utf8没有endian的问题。并不能在编译器里声明一个utf8字符,只能声明一个char数组。机器并不能单独处理一个utf8字符,所有的处理都需要上层控制,也就不存在字节序的问题。utf8标准规定了多字节时的顺序,在大端、小端机器上,都要这么处理。