Have a simple one-off tasks which needs a progress bar. OpenSSL has a useful
callback which one can use for that:
rsa=RSA_generate_key(bits,RSA_F4,progressCallback,NULL);
with
static void callback(int p, int n, void *arg) {
.. stuff
However I want to call this from ObjectiveC without too much ado:
MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
hud.mode = MBProgressHUDModeAnnularDeterminate;
hud.labelText = @"Generating CSR";
[self genReq:^(int p,int n,void *arg) {
hud.progress = --heuristic to guess where we are --
} completionCallback:^{
[MBProgressHUD hideHUDForView:self.view animated:YES];
}];
With Genrec: as an objC method:
-(void)genReq:(void (^)(int,int,void *arg))progressCallback
completionCallback:(void (^)())completionCallback
{
.....
rsa=RSA_generate_key(bits,RSA_F4,progressCallback,NULL);
assert(EVP_PKEY_assign_RSA(pkey,rsa));
rsa=NULL;
....
completionCallback();
}
Now completionCallback(); works splendidly and as expected. But I get a compiler warning/error which I cannot quell for the progress callback:
Passing 'void (^__strong)(int, int, void *)' to parameter of incompatible type 'void (*)(int, int, void *)'
So am curious — what is the appropriate way to do this ?
Thanks,
Dw.
All code is just typed into this answer, test carefully before using!
Function pointers and blocks are not the same thing; the former is just a reference to code, the latter is a closure containing both code and an environment; they are not trivially interchangeable.
You can of course use function pointers in Objective-C, so that is your first option.
If you wish to use blocks then you need to find a way to wrap a block and pass it as a function reference…
The definition of
RSA_generate_keyis:The fourth argument can be anything and is passed as the third argument to the callback; this suggests we could pass the block along with a pointer to a C function which calls it:
And to invoke:
Whether you need any bridge casts (for ARC) is left as an exercise!