Last active
April 5, 2022 15:40
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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