- साथ में
rb_define_methodऔर इसेrb_scan_argsके साथ पार्स कर रहा हूं - रूबी इंटरफ़ेस का उपयोग करना
सी और रूबी:एक परिचय
<पी> जैसा कि उल्लेख किया गया है, रूबी को सी एक्सटेंशन डेवलपर्स के लिए पार्स करना कठिन है। <पी> उदाहरण के लिए: <पी> सी की सुंदरता, जिस भाषा में रूबी लिखी गई है, इसकी सादगी से उत्पन्न होती है, जिसमें इसके फ़ंक्शन पैरामीटर भी शामिल हैं:<data-type> <variable-identifier>...विविध तर्कों के लिए।
रूबी सी एक्सटेंशन में सरल विधि परिभाषा
<पी> हम एक ऐसी विधि से शुरुआत करेंगे जिसका उपयोग आपको किसी बिंदु पर करना होगा,rb_define_method . <पी> आप इस रेपो में कोड उदाहरणों का भी अनुसरण कर सकते हैं। <पी> यहां rb_define_method है के हस्ताक्षर: <पी> और रूबी के एक्सटेंशन.rdoc के अनुसार: <पी> argc तर्कों की संख्या है। यदि argc -1 है, तो फ़ंक्शन को 3 तर्क प्राप्त होंगे:argc, argv, और self। यदि argc -2 है, तो फ़ंक्शन को 2 तर्क प्राप्त होंगे, self और args, जहां args विधि तर्कों की एक रूबी सरणी है। <पी> संक्षेप में: <पी> इसलिए यदि आपके एपीआई में केवल निश्चित पैरामीटर लंबाई वाले तरीके हैं, या केवल एक वैरिएडिक पैरामीटर (def foo(*bar)) है ), आगे न पढ़ें - आपका काम हो गया! यदि आप अपने एपीआई को कॉल करने का बेहतर तरीका चाहते हैं, तो कृपया मेरे मेहमान बनें। <पी> वैसे, यदि आप rb_define_method पर अधिक सम्मिलित उदाहरण चाहते हैं , मेरा सुझाव है कि आप परिभाषित विधियों पर पीटर झू का लेख पढ़ें। पी> रूबी सी एपीआई इंटरनल्स का उपयोग करना
<पी> तो, आइए अपने उपयोग के मामले पर वापस जाएं:जटिल तर्कों को पार्स करना। सौभाग्य से, कुछ उपकरण हमारी मदद कर सकते हैं। <पी> लेकिन पहले, आइए केवलrb_define_method का उपयोग करने की सीमाएं देखें . rb_define_method की कमियां
ब्लॉक तर्कों का कोई उल्लेख नहीं
<पी> एक सीमा यह है किrb_define_method ब्लॉक तर्कों का कभी उल्लेख नहीं करता। उन पर विचार नहीं किया जाता है, क्योंकि अगर आप ब्लॉक पास कर देते हैं तो इससे रूबी को वास्तव में कोई फर्क नहीं पड़ता। आप अभी भीrb_block_given_p का उपयोग करके यह सुनिश्चित कर सकते हैं कि कोई ब्लॉक पास हो गया है या rb_need_block . पीटर झू के लेख में उस विषय पर और भी बहुत कुछ है। आर्ग अलग-अलग हो सकते हैं
<पी> एक और महत्वपूर्ण सीमा यह है कि तर्क अलग-अलग हो सकते हैं, लेकिन मेथडकॉल स्वयं इतना सीमित नहीं है। इसलिए, यदि आप चाहते हैं कि आपका एपीआईdef foo(bar, *baz) जैसा हो , आपको अपने तर्कों का विश्लेषण करना होगा। उस रास्ते पर आपकी मदद करने के लिए कुछ तरीके मौजूद हैं। rb_check_arity वह है जिसे आप rb_define_method के -1 संस्करण के साथ उपयोग कर सकते हैं . <पी> यहां फ़ंक्शन हस्ताक्षर है: कीवर्ड तर्क
<पी> एक आखिरी सीमा जिससे हम गुजरेंगे वह है कीवर्ड तर्कों का उपयोग। और मैंने आखिरी के लिए सर्वश्रेष्ठ रखा, क्योंकि वह इस लेख का मूल होगा। <पी> इससे पहले कि हम उन्हें सही ढंग से पार्स कर सकें, हमें कीवर्ड तर्कों को पुनः प्राप्त करना होगा। सौभाग्य से, रूबी सी एपीआई इसके लिए एक विधि के साथ आती है,rb_scan_args . <पी> यहां rb_scan_args है हस्ताक्षर: <पी> आप rb_scan_args पास कर लें argc और argv rb_define_method द्वारा दिया गया - एक स्ट्रिंग जो बताती है कि तर्कों को कैसे विभाजित किया जाना चाहिए (fmt ) और उन तर्कों के लिए रिसीवर। लीजिए, रूबी के सभी तर्कों की जटिलता को एक पंक्ति में पार्स कर दिया गया है! ख़ैर, लगभग. <पी> fmt के औपचारिक प्रतिनिधित्व के लिए आप एक्सटेंशन.rdoc का संदर्भ ले सकते हैं लिखा जाना चाहिए, हालाँकि हम इसे नीचे दिए गए उदाहरणों में आंशिक रूप से कवर करेंगे। फ़ंक्शन लिखें और पार्स करें:एक उदाहरण
<पी> इस आलेख के शेष भाग के लिए, आइए मान लें कि हम यह फ़ंक्शन लिखना चाहते हैं: <पी>rb_scan_args का उपयोग करके इसे पार्स किया जा रहा है इस तरह दिखेगा: <पी> "1*:" अस्पष्टता का अर्थ है: 1:एक आवश्यक स्थितिगत तर्क*:किसी भी मात्रा में स्थितीय तर्क की आवश्यकता नहीं है::अंत में कीवर्ड तर्क
कीवर्ड तर्कों को पार्स करें
<पी> अब हमने विधि को बाधित कर दिया है, दुर्भाग्य से, हमने अभी तक ऐसा नहीं किया है। हमारा वर्तमान एपीआईdef voronoi_diagram(envelope, *polygons, **kwargs) है . <पी> अंत में, हमें rb_get_kwargs का उपयोग करके उन कीवर्ड तर्कों को पार्स करने की आवश्यकता है . <पी> आपको कुछ आवश्यक और वैकल्पिक तर्क चुनने होंगे। एक बार यह पूरा हो जाने पर, आप table का उपयोग करें रूबी को उन तर्कों का नाम बताने के लिए, और आप परिणाम को एक सरणी (values) में संग्रहीत करते हैं ). <पी> यह आपके पास है! एक जटिल रूबी विधि, जिसे केवल सी का उपयोग करके पार्स किया गया है। हालाँकि, यदि यह आपके लिए बहुत जटिल है, तो एक और विकल्प है। रूबी इंटरफ़ेस का उपयोग करना
<पी> समस्या से निपटने का दूसरा तरीका वास्तव में सीधे रूबी के सिंटैक्स का उपयोग करना और रूबी चरण में पार्सिंग करना है। <पी> इससे आप सीधेrb_define_method के तीसरे फॉर्म का उपयोग कर सकते हैं , एक सी विधि के लिए जो इस तरह दिखती है: <पी> और वहां आप जाते हैं - आप एक शानदार समाधान के साथ समस्या से पूरी तरह से बचते हैं जो वास्तव में रूबी कार्यान्वयन में कुछ तरीकों के लिए उपयोग किया जाता है (Primitive के साथ) क्लास). <पी> हालाँकि एमआरआई द्वारा उपयोग की जाने वाली कक्षा काफी जटिल है और स्वयं सी उत्पन्न करती है, हम इससे प्रेरणा ले सकते हैं। <पी> आइए एक ऑब्जेक्ट बनाएं और दृश्यमान c_voronoi_diagram से बचने के लिए अपने तरीकों को प्लग करें हमारे एपीआई के उपयोगकर्ताओं के लिए: <पी> RGeo के कोडबेस में इस वर्ग का वास्तविक उपयोग मामला देखें। तर्कों को पार्स करना:मुझे किस विधि का उपयोग करना चाहिए?
<पी> यह रेपो एक जटिल रूबी एपीआई स्थापित करने के दो तरीकों को दिखाता है जो सी में लिखा गया है - संक्षेप में:rb_define_methodके साथ और इसेrb_scan_argsके साथ पार्स कर रहा हूं- रूबी इंटरफ़ेस का उपयोग करना
Primitive का उपयोग कर रहे हैं अधिक जटिल तर्कों की अनुमति देने का तरीका। रूबी इंटरफ़ेस का उपयोग करने के लाभ
<पी> मेरी सलाह है कि रूबी इंटरफ़ेस का उपयोग कई कारणों से करें, जिनमें ये भी शामिल हैं:- कोड का आकार छोटा है
- परिवर्तन करना आसान है
rb_define_method का उपयोग करने के लाभ
<पी> हालाँकि, सी संस्करण हमें कुछ बहुत उपयोगी आंतरिक तरीकों का स्वाद देता है। उदाहरण के लिए, rb_check_arity अभी भी वास्तव में उपयोगी है. ब्लॉकों को संभालने के तरीके भी बहुत अच्छे हैं, और आपको रूबी मुखौटा फोरब्लॉक का उपयोग करने की आवश्यकता नहीं हो सकती है। <पी> यह सब आपके उपयोग के मामले के लिए सर्वोत्तम विकल्प ढूंढने के बारे में है। समापन
<पी> इस पोस्ट में, हमने आपके रूबी सी एक्सटेंशन में तर्कों को पार्स करने के दो तरीकों की खोज की है -rb_define_method का उपयोग करके। (संक्षेप में इसकी सीमाओं पर भी नजर डालें) और इसे rb_scan_args के साथ पार्स करें और रूबी इंटरफ़ेस का उपयोग कर रहे हैं। <पी> यदि आप C एक्सटेंशन के बारे में अधिक पढ़ना चाहते हैं, तो मैं अनुशंसा करता हूं: - स्क्रैच से रूबी सी एक्सटेंशन का निर्माण
- सी-साइड के किनारे एक रूबीस्ट की सैर
- मैक पर रूबी सी एक्सटेंशन के साथ काम करना