The BOOL's signature is "B" normally in objective-c, Reference.
But on a 32-bit device. BOOL's signature is "c". Reference
Interesting finding
The interesting thing is that the BOOL in a swift closure is "B" on a 32-bit device (Should be "c").
For example, this is a swift closure.
let closure = {_ in
} as @convention(block) (Bool) -> Void
The closure's signature is v8@?0B4 on 32-bit device. By right it should be v8@?0c4.
How to verify it?
sh_blockSignature
(c code) is the function to get the signature from a block
test.m
enum {
// Set to true on blocks that have captures (and thus are not true
// global blocks) but are known not to escape for various other
// reasons. For backward compatibility with old runtimes, whenever
// BLOCK_IS_NOESCAPE is set, BLOCK_IS_GLOBAL is set too. Copying a
// non-escaping block returns the original block and releasing such a
// block is a no-op, which is exactly how global blocks are handled.
BLOCK_IS_NOESCAPE = (1 << 23),
BLOCK_HAS_COPY_DISPOSE = (1 << 25),
BLOCK_HAS_CTOR = (1 << 26), // helpers have C++ code
BLOCK_IS_GLOBAL = (1 << 28),
BLOCK_HAS_STRET = (1 << 29), // IFF BLOCK_HAS_SIGNATURE
BLOCK_HAS_SIGNATURE = (1 << 30),
};
struct Block_literal_1 {
void *isa; // initialized to &_NSConcreteStackBlock or &_NSConcreteGlobalBlock
int flags;
int reserved;
void (*invoke)(void *, ...);
struct Block_descriptor_1 {
unsigned long int reserved; // NULL
unsigned long int size; // sizeof(struct Block_literal_1)
// optional helper functions
void (*copy_helper)(void *dst, void *src); // IFF (1<<25)
void (*dispose_helper)(void *src); // IFF (1<<25)
// required ABI.2010.3.16
const char *signature; // IFF (1<<30)
} *descriptor;
// imported variables
};
const char * _Nullable sh_blockSignature(id block)
{
struct Block_literal_1 *layout = (__bridge void *)block;
if (!(layout->flags & BLOCK_HAS_SIGNATURE))
return nil;
void *descRef = layout->descriptor;
descRef += 2 * sizeof(unsigned long int);
if (layout->flags & BLOCK_HAS_COPY_DISPOSE)
descRef += 2 * sizeof(void *);
if (!descRef) return nil;
const char *signature = (*(const char **)descRef);
return signature;
}
test2.swift
let closure = {_ in
} as @convention(block) (Bool) -> Void
let p = sh_blockSignature(closure)!
let signature = String.init(cString: p)
print(signature) // "v8@?0B4"
Is this a swift bug on 32-bit device?
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…