6

有一个简单的一次性任务,需要一个进度条。OpenSSL 有一个有用的回调,可以使用它:

rsa=RSA_generate_key(bits,RSA_F4,progressCallback,NULL);

static void callback(int p, int n, void *arg) {
    .. stuff

但是,我想毫不费力地从 ObjectiveC 调用它:

    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];
    }];

使用 Genrec: 作为 objC 方法:

-(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();
}

现在完成回调();工作出色,符合预期。但我收到一个编译器警告/错误,我无法为进度回调平息:

 Passing 'void (^__strong)(int, int, void *)' to parameter of incompatible type 'void (*)(int, int, void *)'

所以我很好奇 - 这样做的适当方法是什么?

谢谢,

德。

4

1 回答 1

7

所有代码都只是输入到这个答案中,使用前请仔细测试!

函数指针和块不是一回事;前者只是对代码的引用,后者是包含代码和环境的闭包;它们不是可以互换的。

你当然可以在 Objective-C 中使用函数指针,所以这是你的第一选择。

如果您想使用块,那么您需要找到一种方法来包装块并将其作为函数引用传递......

的定义RSA_generate_key是:

RSA *RSA_generate_key(int num,
                      unsigned long e,
                      void (*callback)(int,int,void *),
                      void *cb_arg);

第四个参数可以是任何东西,并作为第三个参数传递给回调;这表明我们可以将连同指向调用它的 C 函数的指针一起传递:

typedef void (^BlockCallback)(int,int);

static void callback(int p, int n, void *anon)
{
   BlockCallback theBlock = (BlockCallback)anon; // cast the void * back to a block
   theBlock(p, n);                               // and call the block
}

- (void) genReq:(BlockCallback)progressCallback 
         completionCallback:(void (^)())completionCallback 
{
   .....
   // pass the C wrapper as the function pointer and the block as the callback argument
   rsa = RSA_generate_key(bits, RSA_F4, callback, (void *)progressCallback);
   assert(EVP_PKEY_assign_RSA(pkey,rsa));
   rsa = NULL;
   ....

   completionCallback();
}

并调用:

[self genReq:^(int p, int n)
             {
                hud.progress = --heuristic to guess where we are --
             }
      completionCallback:^{
                            [MBProgressHUD hideHUDForView:self.view animated:YES];
                          }
];

是否需要任何桥接模型(用于 ARC)留作练习!

于 2012-05-04T09:33:08.293 回答