C-to-Swift function calls, are they glued? Specifically, CGEvent.copy()?

Yep. Let's try C code first:

void testC(void) {
    CGEventRef event = CGEventCreateKeyboardEvent(NULL, 1, 1);
    printf("%d\n", myRetainCount(event)); // 1
    printf("%d\n", CFGetRetainCount(event)); // 1
    CGEventRef event2 = CGEventCreateCopy(event);
    printf("%d\n", myRetainCount(event2)); // 1
    printf("%d\n", CFGetRetainCount(event2)); // 1
}

all good here, no surprises.

Using the following helpers on the C side:

int myRetainCount(long param) {
    return ((NSObject*)param).retainCount;
}

int myRetainCount2(long param) {
    return CFGetRetainCount((CFTypeRef)param);
}

int myRetainCount3(CFTypeRef param) {
    return CFGetRetainCount(param);
}

let's try it from swift:

    print(myRetainCount(unsafeBitCast(event, to: Int.self))) // 1
    print(myRetainCount2(unsafeBitCast(event, to: Int.self))) // 1

So far so good. Now:

    print(CFGetRetainCount(event)) // 2

Oops. Passing event inside CFGetRetainCount affects its retain count. But's that only temporary:

    print(myRetainCount2(unsafeBitCast(event, to: Int.self))) // 1, good again

Ditto:

    print(myRetainCount3(event)) // 2, oops
    print(myRetainCount2(unsafeBitCast(event, to: Int.self))) // 1, good again

By using the above "bit cast to int" trick I'm merely disabling all possible retain / release going under the hood when passing a ref-counted parameter inside a function, so it gives correct results.

"event.copy" is CGEventCreateCopy:

    let c = event.copy()!
->  0x100006f1c <+1544>: bl     0x10008f0b4               ; symbol stub for: CGEventCreateCopy

It returns +1 object like all "create" and "copy" calls within Apple ecosystem.

1 Like