6

プログレス バーが必要な単純な 1 回限りのタスクを用意します。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 *)'

興味があります - これを行う適切な方法は何ですか?

ありがとう、

Dw。

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

4 番目の引数は任意で、3 番目の引数としてコールバックに渡されます。これは、ブロックを呼び出す 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 に答える