2012-05-04 21 views
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 साथ OpenSSL एक उपयोगी कॉलबैक जो एक है कि के लिए उपयोग कर सकते हैं : एक ओबीजेसी विधि के रूप में:

-(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 *)' 

तो उत्सुक हूँ: लेकिन मैं एक संकलक चेतावनी/त्रुटि जो मैं प्रगति कॉलबैक के लिए शांत नहीं कर सकता है?

धन्यवाद,

डीडब्ल्यू।

उत्तर

7

सभी कोड सिर्फ इस उत्तर में टाइप किया गया है, प्रयोग करने से पहले सावधानी से परीक्षण करें!

फ़ंक्शन पॉइंटर्स और ब्लॉक समान नहीं हैं; पूर्व कोड का संदर्भ है, उत्तरार्द्ध एक बंद है जिसमें कोड और पर्यावरण दोनों शामिल हैं; वे तुच्छ रूप से विनिमय नहीं कर सकते हैं।

आप निश्चित रूप से उद्देश्य-सी में फ़ंक्शन पॉइंटर्स का उपयोग कर सकते हैं, इसलिए यह आपका पहला विकल्प है।

आप तो ब्लॉक का उपयोग करने के लिए आप एक ब्लॉक लपेट और एक समारोह संदर्भ के रूप में पारित करने के लिए एक रास्ता खोजने की जरूरत चाहते हैं ...

RSA_generate_key की परिभाषा है:

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

चौथी तर्क कुछ भी हो सकता है और कॉलबैक के लिए तीसरे तर्क के रूप में पारित किया जाता है; यह पता चलता है कि हम एक सी समारोह है जो यह कहता है के लिए एक सूचक के साथ ब्लॉक गुजारें सकता:

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

आप किसी भी पुल डाले (एआरसी के लिए) की जरूरत है है एक अभ्यास के रूप में छोड़ दिया!

+0

सबसे लवली! और एआरसी के लिए __bridge की आवश्यकता है। शर्मिंदा है कि किसी को कॉलबैक() के बीच में होना चाहिए - यानी कि कोई प्रगति को पास नहीं कर सकता है (void (*) (int, int, void *)) अपने शून्य (^ __ मजबूत) (int, int, शून्य *) सीधे। –

+0

@ Dirk-WillemvanGulik - ब्लॉक के स्वचालित पासिंग का समर्थन करने का एकमात्र उचित तरीका, यानी एक फंक्शन पॉइंटर (केवल एक कोड सूचक) के रूप में बंद करने के लिए कोड कोड (कोड पॉइंटर + पर्यावरण) को गतिशील रूप से कोड स्टब्स उत्पन्न करना होगा; और इसमें कई कमीएं हैं। सी में सामान्य पैटर्न एक फ़ंक्शन पॉइंटर निर्दिष्ट करना है जो आमतौर पर 'शून्य *' प्रकार का होता है, जिसे उपयोगकर्ता द्वारा परिभाषित वातावरण को पारित करने के लिए उपयोग किया जा सकता है और इस प्रकार मैन्युअल रूप से बंद हो जाता है - और openssl उस पैटर्न और समाधान का पालन करता है उपरोक्त इसका उपयोग करता है। – CRD

+0

साफ़ करें। एक बार फिर धन्यवाद!)।NSStackBlock में खोद गया है और कुल समझ में आता है। –