Skip to content

Instantly share code, notes, and snippets.

@theoknock
Last active April 5, 2022 15:40
Show Gist options
  • Save theoknock/40e1b566ae5e3fc3ca3e032b33b08c5e to your computer and use it in GitHub Desktop.
Save theoknock/40e1b566ae5e3fc3ca3e032b33b08c5e to your computer and use it in GitHub Desktop.
Passing both a block and its parameters via a const void * and back again
// A block that saves both your parameter value and the block that processes it, which ...
// ... takes an unsigned long and returns a block that returns an unsigned long
const unsigned long (^ const __strong predicate_blk_x)(void) = ^ (unsigned long predicate) {
return ^ const unsigned long (void) {
return predicate;
};
}(touch_property); // touch_property is an unsigned int declared and initialized within the scope of this block
// A block that return a const void * to the block above, which...
// allows both the block and its parameter (touch_property) to be passed together using a single pointer
const void * (^ const __strong predicate_blk_t_x)(typeof(const unsigned long (^)(void))) = ^ (typeof(const unsigned long (^)(void)) predicate_blk) {
return Block_copy((const void *)CFBridgingRetain(predicate_blk));
};
// Invoking both blocks above and storing the result in a const void *
const void * predicate_blk_ptr = predicate_blk_t_x(predicate_blk_x);
// A block that takes the const void * above (predicate_blk_ptr) and...
// ... then inokes it to return an unsigned long
const unsigned long l_x = ^ (const void * predicate_expr) {
return ((typeof(const unsigned long (^)(void)))CFBridgingRelease(predicate_expr))();
}(predicate_blk_ptr);
// Prints the unsigned long that was passed as a parameter (touch_property) above
printf("l_x == %lu\n", l_x);
// !-----------!
// Improved version below
// !-----------!
/*
Use the following three blocks to supply the predicate parameter after predicate_blk is passed
*/
const unsigned long (^ const __strong predicate_blk)(const unsigned long) = ^ const unsigned long (const unsigned long predicate) {
return predicate;
};
const void * (^ const __strong predicate_blk_t)(typeof(const unsigned long (^)(const unsigned long))) = ^ (typeof(const unsigned long (^)(const unsigned long)) predicate_blk) {
return Block_copy((const void *)CFBridgingRetain(predicate_blk));
};
const void * predicate_blk_ptr = predicate_blk_t(predicate_blk);
const unsigned long l = ^ (const unsigned long predicate) {
return ^ (const void * predicate_expr) {
return ((typeof(const unsigned long (^)(const unsigned long)))CFBridgingRelease(predicate_expr))(predicate);
}(predicate_blk_ptr);
}(touch_property);
printf("l == %lu\n", l);
/*
Use the following three blocks to supply the predicate parameter before predicate_blk is passed
*/
const unsigned long (^ const __strong predicate_blk_x)(void) = ^ (unsigned long predicate) {
return ^ const unsigned long (void) {
return predicate;
};
}(touch_property);
const void * (^ const __strong predicate_blk_t_x)(typeof(const unsigned long (^)(void))) = ^ (typeof(const unsigned long (^)(void)) predicate_blk) {
return Block_copy((const void *)CFBridgingRetain(predicate_blk));
};
const void * predicate_blk_ptr_x = predicate_blk_t_x(predicate_blk_x);
const unsigned long l_x = ^ (const void * predicate_expr) {
return ((typeof(const unsigned long (^)(void)))CFBridgingRelease(predicate_expr))();
}(predicate_blk_ptr_x);
printf("l_x == %lu\n", l_x);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment