दिलचस्प पोस्ट
StackOverflow के इनपुट टैग की तरह jQuery के स्वत: पूर्ण टैगिंग प्लग-इन? सी # प्री- और पोस्ट इंक्रीमेंट भ्रम VBA के साथ डिफ़ॉल्ट ब्राउज़र में एक html पृष्ठ खोलें? एंड्रॉइड स्टूडियो में मैं 'संपत्ति' फ़ोल्डर कहां रखता हूं? सी ++ टेम्पलेट आंशिक विशेषज्ञता सदस्य समारोह मूल्य से ऑब्जेक्ट निकालने के लिए ऐरे एक्सटेंशन एनिमेशन के माध्यम से एक गतिविधि में स्वैप टुकड़ा C ++ में "const" के उपयोग के कितने और कौन हैं? JqGrid स्तंभ वरीयताओं को जारी रखने के लिए हीरा विरासत (सी ++) विज़ुअल स्टूडियो में दो फाइलों की तुलना करें क्या सबसे मुश्किल बग आप कभी भी पाया और तय है? क्या मतलब है? फोनगैप – एंड्रॉइड ऐप के लिए स्प्लैश स्क्रीन उद्धरण चिह्नों के साथ आस-पास

पायथन में सी लाइब्रेरी को लपेटना: C, Cython या ctypes?

मैं एक पायथन अनुप्रयोग से सी लाइब्रेरी को कॉल करना चाहता हूं। मैं पूरी एपीआई लपेट नहीं करना चाहता, केवल मेरे कार्य के लिए प्रासंगिक फ़ंक्शन और डेटाटेप्स। जैसा कि मैं देख रहा हूं, मेरे पास तीन विकल्प हैं:

  1. सी में एक वास्तविक विस्तार मॉड्यूल बनाएं। संभवतया ओव्हरकिल, और मैं विस्तार लेखन लेखन के ऊपरी भाग से बचना चाहता हूं।
  2. सी लाइब्रेरी से पायथन के संबंधित हिस्सों को बेनकाब करने के लिए Cython का उपयोग करें
  3. संपूर्ण लाइब्रेरी के साथ संचार करने के लिए ctypes का इस्तेमाल करते हुए पायथन में पूरी चीज करें।

मुझे यकीन नहीं है कि क्या 2) या 3) बेहतर विकल्प है। 3 का फायदा यह है कि ctypes मानक पुस्तकालय का हिस्सा है, और परिणामी कोड शुद्ध पायथन होगा – हालांकि मुझे यकीन नहीं है कि वास्तव में यह लाभ कितना बड़ा है

क्या कोई विकल्प या अधिक फायदे हैं? आप किस दृष्टिकोण की सलाह देते हैं?


संपादित करें: आपके सभी उत्तरों के लिए धन्यवाद, वे किसी को कुछ इसी तरह की तलाश करने के लिए एक अच्छा संसाधन प्रदान करते हैं। निश्चित रूप से निर्णय, अभी भी एकल मामले के लिए बनाया जाना है-कोई नहीं "यह सही बात है" प्रकार का उत्तर है मेरे अपने मामले के लिए, मैं शायद सीटीआईपी के साथ जाऊंगा, लेकिन मैं भी किसी अन्य परियोजना में Cython की कोशिश कर रहा हूं।

कोई भी सही जवाब नहीं होने के साथ, एक को स्वीकार करना कुछ हद तक मनमाना है; मैंने FogleBird के उत्तर को चुना क्योंकि यह सीटीआईपी में कुछ अच्छी अंतर्दृष्टि प्रदान करता है और यह वर्तमान में भी सबसे अधिक वोट वाले उत्तर है। हालांकि, मैं एक अच्छी अवलोकन पाने के लिए सभी उत्तरों को पढ़ने का सुझाव देता हूं।

एक बार फिर धन्यवाद।

वेब के समाधान से एकत्रित समाधान "पायथन में सी लाइब्रेरी को लपेटना: C, Cython या ctypes?"

ctypes आपकी जल्द से जल्द करने के लिए सबसे अच्छा शर्त है, और यह काम करने के लिए एक खुशी है क्योंकि आप अभी भी अजगर लिख रहे हैं!

मैंने हाल ही में सीटीआईपी के उपयोग से यूएसबी चिप के साथ संचार करने के लिए एक एफटीडीआई ड्राइवर को लपेट लिया था और यह बहुत अच्छा था। मैंने यह सब किया और एक से कम कार्य दिवस में काम कर रहा था। (मैंने केवल उन फ़ंक्शंस को कार्यान्वित किया, जो हमें आवश्यक था, लगभग 15 फ़ंक्शन)।

हम पहले एक ही उद्देश्य के लिए तृतीय-पक्ष मॉड्यूल, Pyusb का उपयोग कर रहे थे। PyUSB एक वास्तविक सी / पायथन एक्सटेंशन मॉड्यूल है। लेकिन पीयूएसबी जीआईएल को रिलीज नहीं कर रहा था, जिसने पढ़ना / लिखना रोक दिया था, जो हमारे लिए समस्याएं पैदा कर रहा था इसलिए मैंने सीटीआईपीज़ का इस्तेमाल करते हुए अपना खुद का मॉड्यूल लिखा है, जो जीआईएल को देशी फ़ंक्शन बुलाते समय जारी करता है।

ध्यान देने योग्य बात यह है कि सीटीआईपी को पुस्तकालय में #define स्थिर और स्थिर सामग्री के बारे में नहीं पता होगा, केवल फ़ंक्शन, इसलिए आपको अपने कोड में उन स्थिरांक को फिर से परिभाषित करना होगा।

यहां एक उदाहरण दिया गया है कि कैसे कोड समाप्त हो गया (बहुत से बाहर निकला, बस आपको इसका सारांश दिखाने की कोशिश कर रहा है):

 from ctypes import * d2xx = WinDLL('ftd2xx') OK = 0 INVALID_HANDLE = 1 DEVICE_NOT_FOUND = 2 DEVICE_NOT_OPENED = 3 ... def openEx(serial): serial = create_string_buffer(serial) handle = c_int() if d2xx.FT_OpenEx(serial, OPEN_BY_SERIAL_NUMBER, byref(handle)) == OK: return Handle(handle.value) raise D2XXException class Handle(object): def __init__(self, handle): self.handle = handle ... def read(self, bytes): buffer = create_string_buffer(bytes) count = c_int() if d2xx.FT_Read(self.handle, buffer, bytes, byref(count)) == OK: return buffer.raw[:count.value] raise D2XXException def write(self, data): buffer = create_string_buffer(data) count = c_int() bytes = len(data) if d2xx.FT_Write(self.handle, buffer, bytes, byref(count)) == OK: return count.value raise D2XXException 

किसी ने कई विकल्पों पर कुछ बेंचमार्क किए हैं

यदि मुझे सी ++ लाइब्रेरी बहुत सी वर्गों / टेम्पलेट्स / आदि के साथ लपेट करनी पड़ी तो मैं ज्यादा संकोच कर सकता हूं लेकिन ctypes structs के साथ अच्छी तरह से काम करता है और पायथन में कॉलबैक भी कर सकता है।

चेतावनी: एक Cython कोर डेवलपर की राय आगे।

मैं लगभग हमेशा ctypes पर Cython की सिफारिश। इसका कारण यह है कि इसमें बहुत आसान नवीनीकरण पथ है। यदि आप सीटीआईपी का उपयोग करते हैं, तो पहले से बहुत सी चीजें आसान हो जाएंगी, और सादे पायथन में अपने एफएफआई कोड को लिखने में निश्चित रूप से अच्छा होगा, बिना संकलन के, निर्भरताएं और सभी का निर्माण हालांकि, कुछ बिंदु पर, आपको लगभग निश्चित रूप से पता चल जाएगा कि आपको अपने सी लाइब्रेरी में बहुत कुछ करना होगा, या तो किसी लूप में या अन्योन्याश्रित कॉलों की लंबी श्रृंखला में, और आप इसे ऊपर की तरफ बढ़ाना चाहते हैं यही वह बात है जहां आप नोट करेंगे कि आप इसे सीटीआईपी के साथ नहीं कर सकते। या, जब आपको कॉलबैक फ़ंक्शंस की आवश्यकता होती है और आपको लगता है कि आपका पायथन कॉलबैक कोड एक बाधा बन जाता है, तो आप इसे तेज करना चाहते हैं और / या इसे सी में भी नीचे ले जाना चाहते हैं दोबारा, आप इसे सीटीआईपी के साथ नहीं कर सकते। तो आपको उन बिंदुओं पर भाषाओं को स्विच करना होगा और अपने कोड के कुछ हिस्सों को फिर से लिखना शुरू करना होगा, संभावित रूप से आपके पायथन / सीटीआईपी कोड को सादे सी में बदलना होगा, इस प्रकार आपके कोड को सदा पायथन में पहले स्थान पर लिखने का पूरा लाभ खराब होगा।

सिथन के साथ, ओटोह, आप पूरी तरह से निःशुल्क और कॉलिंग कोड को पतला या मोटी के रूप में मुफ्त में लेना चाहते हैं। आप अपने सी कोड को नियमित पायथन कोड से सरल कॉल से प्रारंभ कर सकते हैं, और Cython उन्हें किसी भी अतिरिक्त कॉलिंग ओवरहेड के बिना देशी सी कॉल में अनुवाद करेंगे और पायथन पैरामीटर के लिए बहुत कम कनवर्ज़न ओवरहेड के साथ। जब आप देखते हैं कि आपको कुछ बिंदु पर और अधिक प्रदर्शन की आवश्यकता होती है, जहां आप अपनी सी लाइब्रेरी में बहुत अधिक महंगी कॉल कर रहे हैं, तो आप अपने आसपास के अजगर कोड को स्थिर प्रकार के साथ एनोटेट करना शुरू कर सकते हैं और Cython को सीधे सी में अपने लिए ऑप्टिमाइज़ कर सकते हैं। या, आप कॉल से बचने के लिए और अपने लूप को एल्गोरिथम रूप से कसने के लिए Cython में अपने सी कोड के कुछ हिस्सों को फिर से लिखना शुरू कर सकते हैं। और अगर आपको तेजी से कॉलबैक की आवश्यकता है, तो बस उपयुक्त हस्ताक्षर के साथ एक फ़ंक्शन लिखें और इसे सी कॉलबैक रजिस्ट्री में सीधे पास करें। फिर, कोई ओवरहेड नहीं है, और यह आपको सादे सी कॉलिंग प्रदर्शन देता है। और बहुत कम संभावना के मामले में आप वास्तव में सिथन में अपने कोड को पर्याप्त रूप से नहीं प्राप्त कर सकते हैं, फिर भी आप सी (या सी ++ या फोरट्रान) में इसके महत्वपूर्ण हिस्सों को पुनः लिखने पर विचार कर सकते हैं और इसे अपने सिथॉन कोड से स्वाभाविक रूप से और मूल रूप से कॉल कर सकते हैं। लेकिन फिर, यह वास्तव में केवल एक विकल्प के बजाय अंतिम उपाय बन जाता है।

इसलिए, सीटीपीपी सरल चीजें करने के लिए अच्छा है और जल्दी से कुछ चलने के लिए। हालांकि, जैसे ही चीजें बढ़ने लगती हैं, आप अधिकतर संभावना उस बिंदु पर पहुंच जाएंगे जहां आप ध्यान दें कि आपने शुरुआत से ही सीथन का बेहतर इस्तेमाल किया था

Cython अपने आप में एक बहुत अच्छा उपकरण है, अच्छी तरह से सीखने लायक है, और आश्चर्यजनक रूप से पायथन वाक्यविन्यास के करीब है। यदि आप नम्पी के साथ कोई वैज्ञानिक कंप्यूटिंग करते हैं, तो Cython जाने का एक तरीका है क्योंकि यह मैट्रिक्स संचालन के लिए नम्पी के साथ एकीकृत है।

सिथन पायथन भाषा का एक सुपरसेट है आप किसी भी वैध पायथन फ़ाइल को उस पर फेंक सकते हैं, और यह एक वैध सी प्रोग्राम को बाहर कर देगा। इस स्थिति में, सिथन सिर्फ पायथन को अंतर्निहित CPython API पर कॉल करेगा यह शायद एक 50% गति में परिणाम होता है क्योंकि आपका कोड अब व्याख्या नहीं करता है।

कुछ अनुकूलन प्राप्त करने के लिए, आपको अपने कोड के बारे में Cython अतिरिक्त तथ्य, जैसे कि प्रकार घोषणाएं, को प्रारंभ करना होगा यदि आप इसे पर्याप्त बताते हैं, तो यह कोड को शुद्ध सी में उबाल कर सकता है। यही है, पायथन में लूप के लिए सी में लूप के लिए एक हो जाता है। यहां आपको भारी गति लाभ मिलेगा। आप बाहरी सी कार्यक्रमों से भी लिंक कर सकते हैं।

सिथन कोड का उपयोग करना भी अविश्वसनीय रूप से आसान है मैंने सोचा कि मैनुअल ने इसे कठिन बना दिया है आप सचमुच ऐसा करते हैं:

 $ cython mymodule.pyx $ gcc [some arguments here] mymodule.c -o mymodule.so 

और फिर आप अपने पायथन कोड में import mymodule कर सकते हैं और पूरी तरह से भूल जाते हैं कि यह सी के लिए तैयार है।

किसी भी स्थिति में, क्योंकि Cython बहुत आसान है और उपयोग करना शुरू करने के लिए, मैं यह देखने की कोशिश करता हूं कि यह आपकी आवश्यकताओं के अनुरूप है या नहीं। यह कचरा नहीं होगा, यदि वह ऐसा उपकरण न हो जो आप ढूंढ रहे हों।

एक पायथन अनुप्रयोग से सी लाइब्रेरी को कॉल करने के लिए सीएफआईपी के लिए एक नया विकल्प है जो सीएफआईआई भी है। यह एफएफआई के लिए एक नया रूप लाता है:

  • यह एक आकर्षक, स्वच्छ तरीके से समस्या को संभालता है ( सीटीआईपी के विपरीत)
  • यह गैर पायथन कोड लिखने की आवश्यकता नहीं है ( SWIG, Cython , … के रूप में)

मैं वहाँ एक और बाहर फेंक दूँगा: SWIG

यह सीखना आसान है, बहुत सी बातें करता है, और कई भाषाओं का समर्थन करता है, इसलिए जो सीखने का समय लगता है वह बहुत उपयोगी हो सकता है।

यदि आप SWIG का उपयोग करते हैं, तो आप एक नया अजगर विस्तार मॉड्यूल बना रहे हैं, लेकिन SWIG आपके लिए भारी भार उठाने के साथ अधिकतर है।

व्यक्तिगत रूप से, मैं सी में एक एक्सटेंशन मॉड्यूल लिखूंगा। पायथन सी एक्सटेंशन से भयभीत न हो – वे लिखने के लिए बिल्कुल भी मुश्किल नहीं हैं प्रलेखन बहुत स्पष्ट और उपयोगी है जब मैंने पहली बार पायथन में एक सी एक्सटेंशन लिखा था, तो मुझे लगता है कि मुझे यह लिखने के लिए एक घंटे लग गए कि कैसे लिखना है – बिल्कुल ज्यादा समय नहीं।

ctypes महान है जब आप पहले से ही एक संकलित लाइब्रेरी ब्लॉब (जैसे ओएस पुस्तकालयों) से निपटने के लिए मिल गया है। कॉलिंग ओवरहेड गंभीर है, हालांकि, यदि आप लाइब्रेरी में बहुत सी कॉल कर रहे हैं, और आप वैसे भी सी कोड लिख रहे हैं (या कम से कम इसे संकलित कर रहे हैं), मैं कहता हूं cython यह अधिक काम नहीं है, और परिणामस्वरूप पीआईडी ​​फ़ाइल का उपयोग करने के लिए यह बहुत तेज़ और अधिक अजगर होगा।

मैं व्यक्तिगत रूप से अजगर कोड के त्वरित गतियों के लिए सिथन का इस्तेमाल करते हैं (loops और पूर्णांक तुलना दो क्षेत्र हैं जहां सिथन विशेष रूप से चमकता है), और जब इसमें शामिल अन्य लाइब्रेरीज़ के कुछ अधिक कोड / रैपिंग होते हैं, तो मैं बूस्ट को बदलूंगा । Python Boost.Python स्थापित करने के लिए नकचढ़ा हो सकता है, लेकिन एक बार आप इसे काम मिल गया है, यह सी / सी + + सीधा कोड लपेटकर बनाता है।

Cython नमूनों लपेटने में भी महान है (जो मैंने SciPy 2009 की कार्यवाही से सीखा है), लेकिन मैंने नमूनी का इस्तेमाल नहीं किया है, इसलिए मैं उस पर टिप्पणी नहीं कर सकता।

यदि आपके पास पहले से एक परिभाषित एपीआई के साथ एक पुस्तकालय है, मुझे लगता है कि ctypes सबसे अच्छा विकल्प है, क्योंकि आपको केवल एक छोटे से आरंभ करना होगा और फिर पुस्तकालय को जिस तरह से आप उपयोग किया गया है उतनी अधिक या कम कॉल करना होगा

मुझे लगता है कि Cython या सी में एक विस्तार मॉड्यूल बनाने (जो कि बहुत मुश्किल नहीं है) अधिक उपयोगी होते हैं जब आपको नया कोड की आवश्यकता होती है, जैसे कि लाइब्रेरी को बुला रहा है और कुछ जटिल, समय-व्यतीत कार्य करता है, और फिर परिणाम को पायथन को पास कर रहा है

सरल कार्यक्रमों के लिए एक अन्य दृष्टिकोण सीधे एक अलग प्रक्रिया (बाहरी रूप से संकलित) करता है, परिणाम को मानक आउटपुट में आउटपुट करता है और उसे सबप्रोसेस मॉड्यूल के साथ कॉल करता है। कभी-कभी यह सबसे आसान तरीका है

उदाहरण के लिए, यदि आप कंसोल सी प्रोग्राम बनाते हैं जो इस तरह से अधिक या कम काम करता है

 $miCcode 10 Result: 12345678 

आप इसे अजगर से कह सकते हैं

 >>> import subprocess >>> p = subprocess.Popen(['miCcode', '10'], shell=True, stdout=subprocess.PIPE) >>> std_out, std_err = p.communicate() >>> print std_out Result: 12345678 

थोड़ी सी स्ट्रिंग बनाने के साथ, आप किसी भी तरह से परिणाम चाहते हैं। आप मानक त्रुटि आउटपुट को भी कैप्चर कर सकते हैं, इसलिए यह काफी लचीला है

एक मुद्दा है जिसने मुझे सीटीआईपी का इस्तेमाल नहीं किया और न ही सिथन और जो अन्य उत्तरों में उल्लिखित नहीं है।

सीटीआईपी का उपयोग करना परिणाम कम्पाइलर पर निर्भर नहीं करता है जो आप बिल्कुल भी उपयोग कर रहे हैं। आप एक लाइब्रेरी लिखकर अधिक से कम किसी भी भाषा का उपयोग कर सकते हैं, जिसे देशी साझा लाइब्रेरी में संकलित किया जा सकता है। इससे कोई फर्क नहीं पड़ता है, कौन सा सिस्टम, कौन सी भाषा और कम्पाइलर सिथन, हालांकि, बुनियादी सुविधाओं से सीमित है उदाहरण के लिए, यदि आप खिड़कियों पर इंटेल कंपाइलर का उपयोग करना चाहते हैं, तो साइथॉन काम करने के लिए यह बहुत अधिक मुश्किल है: आपको "इंफॉर्मेशन" कम्पाइलर को सिथन करना चाहिए, इस सटीक कंपाइलर के साथ कुछ को पुनः कंपाइल करना चाहिए।

यदि आप विंडोज को लक्षित करते हैं और कुछ स्वामित्व C ++ लाइब्रेरीज़ को लपेटते हैं, तो आपको जल्द ही पता चल जाएगा कि msvcrt***.dll (Visual C ++ Runtime) के अलग-अलग संस्करण थोड़ा असंगत हैं।

इसका अर्थ है कि आप Cython का उपयोग करने में सक्षम नहीं हो सकते हैं, जिसके परिणामस्वरूप msvcr90.dll को msvcr90.dll (Python 2.7) या msvcr100.dll (पायथन 3.x) से लिंक किया गया है। यदि आप लपेटते हैं, तो लाइब्रेरी रनटाइम के अलग-अलग संस्करण के साथ जुड़ा हुआ है, तो आप भाग्य से बाहर हैं।

फिर काम करने के लिए आपको C ++ लाइब्रेरीज़ के लिए सी रैपर बनाने की आवश्यकता होगी, उस रैपर डीएलएल को msvcrt***.dll के समान संस्करण के रूप में लिंक करें। और फिर ctypes का इस्तेमाल अपने हाथ से लुढ़का आवरण डीएलएल गतिशील रूप से रनटाइम पर लोड करने के लिए करें।

तो बहुत सारे छोटे विवरण हैं, जिन्हें निम्नलिखित लेख में बहुत कुछ बताया गया है:

"सुंदर मूल पुस्तकालय (पायथन में) ": http://lucumr.pocoo.org/2013/8/18/beautiful-native-libraries/

GLib का उपयोग करने वाले पुस्तकालयों के लिए जीओबीजेक्ट इंट्रोस्पेक्शन का उपयोग करने की भी एक संभावना है