मेरे पास कुछ तर्क स्वीकार करने वाले ब्लॉक के साथ एक चर है। तर्कों और उनके प्रकार की सटीक संख्या भिन्न हो सकती है। उदाहरण के लिए यह एक ब्लॉकब्लॉक के तर्क संख्या और प्रकार भिन्न हो सकते हैं जब va_list से तर्क के साथ कॉल ब्लॉक
void(^testBlock1)(int) = ^(int i){}
या एक ब्लॉक
void(^testBlock2)(NSString *,BOOL,int,float) = ^(NSString *str,BOOL b,int i,float f){}
तर्क प्रकार {id, BOOL, char, int, unsigned int, float}
तक ही सीमित हैं हो सकता है।
मुझे तर्कों और उनके प्रकार की वर्तमान गणना पता है। मैं एक विधि है जो दिए गए तर्क के साथ ब्लॉक निष्पादित कर सकते हैं लागू करने की आवश्यकता:
-(void)runBlock:(id)block withArguments:(va_list)arguments
types:(const char *)types count:(NSUInteger)count;
मेरे पास अनुभवहीन समाधान काम कर रहा है, लेकिन यह काफी बदसूरत है, अधिक से अधिक 4 बाइट आकार का केवल प्रकार का समर्थन करता है और संरेखण पर निर्भर करता है। तो मैं कुछ बेहतर खोज रहा हूँ।
#define MAX_ARGS_COUNT 5
-(void)runBlock:(id)block withArguments:(va_list)arguments
types:(const char *)types count:(NSUInteger)count{
// We will store arguments in this array.
void * args_table[MAX_ARGS_COUNT];
// Filling array with arguments
for (int i=0; i<count; ++i) {
switch (types[i]) {
case '@':
case 'c':
case 'i':
case 'I':
args_table[i] = (void *)(va_arg(arguments, int));
break;
case 'f':
*((float *)(args_table+i)) = (float)(va_arg(arguments, double));
break;
default:
@throw [NSException exceptionWithName:@"runBlock" reason:[NSString stringWithFormat:@"unsupported type %c",types[i]] userInfo:nil];
break;
}
}
// Now we need to call our block with appropriate count of arguments
#define ARG(N) args_table[N]
#define BLOCK_ARG1 void(^)(void *)
#define BLOCK_ARG2 void(^)(void *,void *)
#define BLOCK_ARG3 void(^)(void *,void *,void *)
#define BLOCK_ARG4 void(^)(void *,void *,void *,void *)
#define BLOCK_ARG5 void(^)(void *,void *,void *,void *,void *)
#define BLOCK_ARG(N) BLOCK_ARG##N
switch (count) {
case 1:
((BLOCK_ARG(1))block)(ARG(0));
break;
case 2:
((BLOCK_ARG(2))block)(ARG(0),ARG(1));
break;
case 3:
((BLOCK_ARG(3))block)(ARG(0),ARG(1),ARG(2));
break;
case 4:
((BLOCK_ARG(4))block)(ARG(0),ARG(1),ARG(2),ARG(3));
break;
case 5:
((BLOCK_ARG(5))block)(ARG(0),ARG(1),ARG(2),ARG(3),ARG(4));
break;
default:
break;
}
}
उत्तर के लिए धन्यवाद। मेरे पास पहले से ही तर्क और उनके प्रकार की सूची है। और हाँ, मैं _invoke_ फ़ंक्शन पॉइंटर ढूंढ और पकड़ सकता हूं। लेकिन मैं इसे विशेष रूप से अपने 'BLOCK_ARG (N) 'मैक्रोज़ के लिए कास्टिंग और तर्कों के लिए एक अस्थायी सरणी से बेहतर तरीके से कैसे कॉल कर सकता हूं? क्या 'ffi_call' को छोड़कर कोई अन्य समाधान है? ** libffi का उपयोग ** मेरे छोटे काम के लिए बहुत अधिक दिखता है। – Yan
वैसे यह बात है - आपको सी उम्मीदों के तरीके में पैरामीटर सेट अप करने के लिए असेंबली का उपयोग करना होगा। यही एनएसआईएनवोकेशन और ऑब्जेक्टिव-सी रनटाइम के कई अन्य गड़बड़ है क्योंकि सी में कुछ रजिस्टरों में तर्कों को निर्धारित किया जाना चाहिए, जो एक निश्चित तरीके से ढेर पर फैलते हैं। प्लेटफ़ॉर्म (x86, x64, ARM) के आधार पर यह परिवर्तन। – russbishop