如何计算ObjC方法类型编码中的数字?

Eci*_*ana 12 objective-c objective-c-runtime

是对我上一个问题的后续跟踪: ObjC方法类型编码字符串中的数字是什么?

说有一个编码:

v24@0:4:8@12B16@20
Run Code Online (Sandbox Code Playgroud)

这些数字是如何计算的?B是一个字符,所以它应该只占用1个字节(而不是4个字节).它与"对齐"有关吗?大小是void多少?

如下计算数字是否正确?询问sizeof每个项目并将结果四舍五入到4的倍数?第一个数字成为所有其他数字的总和?

bbu*_*bum 17

这些数字在m68K天用于表示堆栈布局.也就是说,您可以逐字解码方法签名,对于几乎所有类型,确切地知道堆栈帧中哪些偏移量可以用来获取/设置参数.

这是有效的,因为m68K的ABI完全是[IIRC--已经很长时间]基于堆栈的参数/回传.跨越呼叫边界没有任何东西被塞进寄存器中.

但是,当Objective-C被移植到其他平台时,堆栈中的永远不再是调用约定.参数和返回值通常在寄存器中传递.

因此,那些抵消现在是无用的.同时,由编译器使用的编码类型不再是完整的(因为它永远不会是非常有用的),而且将是不会被编码类型.没有提及编码一些C++模板化类型会产生方法类型编码字符串,其大小可以是多千字节(我认为我遇到的记录大约是30K的类型信息).

所以,不,用它sizeof()来生成数字是不正确的,因为它们对所有事物都毫无意义.它们仍然存在的唯一原因是二进制兼容性; 这里和那里有一些深奥的代码仍在解析类型编码字符串,期望会有随机数字洒在这里和那里.

请注意,ObjC运行时中存在API的残余,这仍然使人们相信可以动态编码/解码堆栈帧.实际上并不是因为C ABI不能保证在优化过程中跨越调用边界保留参数寄存器.你必须下降到组装事情变得丑陋真的真的快(>不寒而栗<).

  • 我可以确认`NSMethodSignature`期望`signatureWithObjCTypes:`的非空类型字符串,并且摆弄具有不正确方法签名的`NSInvocation`很可能引发异常(例如,`getArgument:atIndex:`依赖于与方法签名的`numberOfArguments`相同的信息进行边界检查.@EcirHana (2认同)

rob*_*off 9

完整的编码字符串由该方法构建(在clang中)ASTContext::getObjCEncodingForMethodDecl,您可以在其中找到该字符串lib/AST/ASTContext.cpp.

执行大小舍入的方法是ASTContext::getObjCEncodingTypeSize在同一文件中.它强制每个尺寸至少是一个尺寸int.在Apple目前的所有平台上,a int都是4个字节.