Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/113.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c ObjC模块和;openssl C回调_Objective C_Ios_Callback_Openssl_Block - Fatal编程技术网

Objective c ObjC模块和;openssl C回调

Objective c ObjC模块和;openssl C回调,objective-c,ios,callback,openssl,block,Objective C,Ios,Callback,Openssl,Block,有一个简单的一次性任务,需要一个进度条。OpenSSL有一个有用的 您可以使用哪个回调函数: rsa=RSA_generate_key(bits,RSA_F4,progressCallback,NULL); 与 但是,我想从ObjectiveC中调用此函数,而不需要太多麻烦: MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES]; hud.mode = MBProgressHUDMo

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

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

但是,我想从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();
}
现在是completionCallback();工作出色,如期而至。但我收到一个编译器警告/错误,我无法为进度回调消除该警告/错误:

 Passing 'void (^__strong)(int, int, void *)' to parameter of incompatible type 'void (*)(int, int, void *)'
所以我很好奇,做这件事的合适方法是什么

谢谢


Dw.

所有代码都是在这个答案中键入的,请在使用前仔细测试

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

当然,您可以在Objective-C中使用函数指针,因此这是您的第一个选择

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

RSA\u generate\u 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)留作练习

太可爱了!而____桥就是ARC所需要的一切。遗憾的是,我们需要将callback()放在两者之间,也就是说,我们不能将progressCallback作为(void(*)(int,int,void*)直接从它的void(^强)(int,int,void*))传递出去。@Dirk WillemvanGulik-支持自动传递块的唯一合理方法,即闭包(代码指针+环境)作为函数指针(只是一个代码指针)将是动态生成代码存根;这有各种缺点。C中的常见模式是指定一个函数指针,该指针采用额外的值,通常类型为
void*
,可用于传递用户定义的环境,从而手动构造一个闭包,openssl遵循该模式,而上面的解决方案就是u明白了。再次感谢你。我已经深入研究了NSStackBlock,完全有道理。
[self genReq:^(int p, int n)
             {
                hud.progress = --heuristic to guess where we are --
             }
      completionCallback:^{
                            [MBProgressHUD hideHUDForView:self.view animated:YES];
                          }
];