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


284

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

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

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

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


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

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

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


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

1
अब तुम्हारे पास वही है जो तुम खोज रहे थे। चार अलग-अलग उत्तर। (किसी ने SWIG भी पाया)। इसका मतलब है कि अब आपके पास 3 के बजाय 4 विकल्प हैं
लुका रहने का समय

@ralu यही मैं भी हूं, लेकिन :-) गंभीरता से, मुझे उम्मीद नहीं थी (या चाहते हैं) एक समर्थक / चोर टेबल या एक ही जवाब "यहां आपको क्या करने की आवश्यकता है" कहा गया है। निर्णय लेने के बारे में किसी भी सवाल का जवाब उनके कारणों को देने वाले प्रत्येक संभावित विकल्प के "प्रशंसकों" के साथ दिया जाता है। समुदाय मतदान तब अपना हिस्सा करता है, जैसा कि मेरा अपना काम करता है (तर्कों को देखते हुए, उन्हें मेरे मामले में लागू करना, उपलब्ध स्रोतों को पढ़ना, आदि)। लंबी कहानी छोटी: यहाँ कुछ अच्छे उत्तर हैं।
बेलफा

तो आप किस दृष्टिकोण के साथ जाने वाले हैं? :)

1
जहां तक ​​मुझे पता है (कृपया मुझे सही करें अगर मैं गलत हूं), साइथॉन पाइरेक्स का एक कांटा है जिसमें अधिक विकास हो रहा है, जिससे पाइरेक्स बहुत अधिक अप्रचलित हो गया है।
बाल्फा डेस

जवाबों:


115

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

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

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

एक बात का ध्यान रखें कि ctypes #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

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

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


5
Ctypes के लिए प्रशंसा में शामिल होना, लेकिन एक (अनिर्दिष्ट) मुद्दे पर ध्यान दें: ctypes forking का समर्थन नहीं करता है। यदि आप ctypes का उपयोग करते हुए एक प्रक्रिया से कांटा करते हैं, और माता-पिता और बच्चे दोनों प्रक्रिया ctypes का उपयोग करना जारी रखते हैं, तो आप एक गंदा बग पर ठोकर खाएंगे जिसे साझा मेमोरी का उपयोग करके ctypes के साथ करना है।
ओरेन शेमेश

1
@OrenShemesh क्या इस मुद्दे पर आगे पढ़ने से आप मुझे इंगित कर सकते हैं? मुझे लगता है कि मैं एक ऐसी परियोजना के साथ सुरक्षित रह सकता हूं, जिस पर मैं वर्तमान में काम कर रहा हूं, क्योंकि मेरा मानना ​​है कि केवल माता-पिता प्रक्रिया का उपयोग ctypes(के लिए pyinotify) करते हैं, लेकिन मैं समस्या को अधिक अच्छी तरह से समझना चाहता हूं।
जिग

यह मार्ग मुझे बहुत मदद करता है One thing to note is that ctypes won't know about #define constants and stuff in the library you're using, only the functions, so you'll have to redefine those constants in your own code.इसलिए, मुझे उन स्थिरांक को परिभाषित करना होगा जो वहाँ हैं winioctl.h....
स्वदेव

प्रदर्शन के बारे में कैसे? ctypesसी-एक्सटेंशन की तुलना में बहुत धीमा है क्योंकि टोंटी पाइथन से सी तक इंटरफ़ेस है
टॉमस्वायर

154

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

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

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

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


4
+1 वे अच्छे अंक हैं, बहुत बहुत धन्यवाद! हालांकि मुझे आश्चर्य है कि केवल टोंटी के हिस्सों को साइथन में ले जाना वास्तव में यह ओवरहेड का इतना हिस्सा है। लेकिन मैं मानता हूं, यदि आप किसी भी प्रकार के प्रदर्शन के मुद्दों की अपेक्षा करते हैं, तो आप शुरुआत से ही साइथन का उपयोग कर सकते हैं।
बेलफा

क्या यह अभी भी सी और पायथन दोनों के साथ अनुभवी प्रोग्रामरों के लिए है? उस स्थिति में कोई यह तर्क दे सकता है कि पायथन / ctypes बेहतर विकल्प है, क्योंकि C लूप्स (SIMD) का वेक्टरकरण कभी-कभी अधिक सरल होता है। लेकिन, इसके अलावा, मैं किसी भी साइथन कमियों के बारे में नहीं सोच सकता।
एलेक्स वैन हाउटेन

जवाब के लिए धन्यवाद! साइथॉन के बारे में मुझे एक बात परेशान करने वाली थी कि बिल्ड की प्रक्रिया सही हो रही है (लेकिन इसका भी मुझे पहले कभी कोई पायथन मॉड्यूल नहीं लिखना है) - क्या मुझे इसे पहले संकलित करना चाहिए, या साइथिस्ट और इसी तरह के प्रश्नों में साइथॉन स्रोत फ़ाइलों को शामिल करना चाहिए। मैंने इस बारे में एक ब्लॉग पोस्ट लिखा है कि किसी को भी ऐसी ही समस्या / शंका है: martinsosic.com/development/2016/02/08/…
Martinsos

जवाब के लिए धन्यवाद! जब मैं साइथन का उपयोग करता हूं तो एक कमी यह है कि ऑपरेटर ओवरलोडिंग पूरी तरह से लागू नहीं होती है (उदाहरण के लिए __radd__)। जब आप अपनी कक्षा के लिए बिलिन प्रकार (जैसे intऔर float) के साथ बातचीत करने की योजना बनाते हैं तो यह स्पष्ट रूप से कष्टप्रद है । इसके अलावा, साइथन में जादू की विधियां सामान्य रूप से थोड़ी छोटी हैं।
मोनोलिथ

100

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

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

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

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

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

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

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


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

18
"आप इस पर किसी भी मान्य पायथन फ़ाइल को फेंक सकते हैं, और यह एक मान्य सी प्रोग्राम को थूक देगा।" <- बिलकुल नहीं, कुछ सीमाएँ हैं: docs.cython.org/src/userguide/limitations.html संभवतः अधिकांश उपयोग के मामलों के लिए कोई समस्या नहीं है, लेकिन बस पूरा होना चाहता था।
रैंडी सीरिंग

7
प्रत्येक रिलीज़ के साथ मुद्दे कम हो रहे हैं, इस बिंदु पर कि पृष्ठ अब कहता है "अधिकांश मुद्दे 0.15 में हल किए गए हैं"।
हेनरी गोमर्सल

3
जोड़ने के लिए, साइथन कोड आयात करने के लिए एक ईवीएन आसान तरीका है: अपने साइथॉन कोड को एक mymod.pyxमॉड्यूल के रूप में लिखें और फिर करें import pyximport; pyximport.install(); import mymodऔर संकलन पर्दे के पीछे होता है।
कौशिक घोष

3
@kaushik यहां तक ​​कि सरल भी pypi.python.org/pypi/runcython है । बस उपयोग करें runcython mymodule.pyx। और pyximport के विपरीत आप इसे अधिक मांग वाले लिंकिंग कार्यों के लिए उपयोग कर सकते हैं। केवल चेतावनी यह है कि मैं वह हूं जिसने इसके लिए बैश की 20 पंक्तियां लिखी हैं और पक्षपाती हो सकता हूं।
रसेलस्टवर्ट

42

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

  • यह समस्या को आकर्षक, स्वच्छ तरीके से ( ctypes के विपरीत ) संभालता है
  • इसे नॉन पायथन कोड लिखने की आवश्यकता नहीं है (जैसा कि SWIG, साइथन , ...)

निश्चित रूप से रैपिंग के लिए जाने का रास्ता , जैसा कि ओपी चाहता था। साइथॉन उन्हें खुद को हॉट लूप लिखने के लिए बहुत अच्छा लगता है, लेकिन इंटरफेस के लिए, cffi बस ctypes से एक सीधा अपग्रेड है।
उड़ान भेड़

21

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

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

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


18

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


सी लाइब्रेरी लपेटना। आप वास्तव में यहां कोड पा सकते हैं: github.com/mdippery/lehmer
mipadi

1
@forivall: कोड वास्तव में यह सब उपयोगी नहीं था, और वहाँ बेहतर यादृच्छिक संख्या जनरेटर हैं। मेरे पास केवल अपने कंप्यूटर पर बैकअप है।
मियादी

2
माना। पायथन का सी-एपीआई लगभग उतना डरावना नहीं है जितना दिखता है (यह मानते हुए कि आप सी जानते हैं)। हालाँकि, पुस्तकालयों, संसाधनों, और डेवलपर्स के अजगर और इसके भंडार के विपरीत, जब आप सी में मूल रूप से एक्सटेंशन लिखते हैं तो आप मूल रूप से अपने स्वयं के होते हैं। संभवतः इसकी एकमात्र खामी (उन लोगों के अलावा जो आमतौर पर सी में लिखने के साथ आती है)।
नोब सैबोट

1
@ मिपाडी: ठीक है, लेकिन वे पायथन 2.x और 3.x के बीच भिन्न हैं, इसलिए अपने विस्तार को लिखने के लिए साइथन का उपयोग करना अधिक सुविधाजनक है, साइथन ने सभी विवरणों का पता लगाया और फिर पायथन 2.30 या उसके लिए उत्पन्न सी कोड संकलित किया। 3.x आवश्यकतानुसार।
0xC0000022L

2
@ मिपाडी ऐसा लगता है जैसे जीथब लिंक मर चुका है और यह आर्काइव.ऑर्ग पर उपलब्ध नहीं है, क्या आपके पास बैकअप है?
jrh

11

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

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

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


11

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

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

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

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

$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

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


हालांकि इस जवाब में कुछ भी गलत नहीं है, लोगों को सतर्क रहना चाहिए, अगर कोड को दूसरों द्वारा एक्सेस करने के लिए खोला जाए, क्योंकि सबप्रोसेस को कॉल करने के साथ shell=Trueआसानी से किसी तरह का शोषण हो सकता है जब कोई उपयोगकर्ता वास्तव में शेल प्राप्त करता है। यह ठीक है जब डेवलपर एकमात्र उपयोगकर्ता है, लेकिन दुनिया में बाहर कष्टप्रद चुभन का एक पूरा गुच्छा है, बस कुछ इस तरह की प्रतीक्षा कर रहा है।
बेन

7

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

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


4

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

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

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

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

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


उस लेख का Microsoft कंपाइलर्स की संगतता के साथ आपके द्वारा लाए जाने वाले मुद्दों से कोई लेना-देना नहीं है। विंडोज पर काम करने वाले साइथन एक्सटेंशन प्राप्त करना वास्तव में बहुत कठिन नहीं है। मैं बहुत ज्यादा सब कुछ के लिए MinGW का उपयोग करने में सक्षम है। एक अच्छा अजगर वितरण हालांकि मदद करता है।
इयान एचएच

2
खिड़कियों पर एक संभावित मुद्दे का उल्लेख करने के लिए +1 (जो मैं वर्तमान में भी कर रहा हूं ...)। @ यह सामान्य रूप से खिड़कियों के बारे में कम है, लेकिन यह एक गड़बड़ है अगर आप किसी दिए गए तीसरे पक्ष के साथ फंस गए हैं जो आपके प्याज़ वितरण से मेल नहीं खाता है।
सेबस्टियन


2

मुझे पता है कि यह एक पुराना सवाल है, लेकिन यह बात गूगल पर तब आती है जब आप सामान खोजते हैं ctypes vs cython, और यहां अधिकांश उत्तर उन लोगों द्वारा लिखे जाते हैं, जो पहले से ही कुशल हैं cythonया cजो आपको सीखने के लिए निवेश करने के लिए आवश्यक वास्तविक समय को प्रतिबिंबित नहीं कर सकते हैं। अपने समाधान को लागू करने के लिए। मैं दोनों में एक पूरी शुरुआत हूं। मैंने पहले कभी नहीं छुआ है cython, और मुझे बहुत कम अनुभव हैc/c++

पिछले दो दिनों से, मैं अपने कोड के प्रदर्शन वाले हिस्से को अजगर से कुछ अधिक निम्न स्तर पर सौंपने के लिए एक रास्ता तलाश रहा था। मैं दोनों में मेरी कोड लागू किया ctypesऔरCython है, जो दो सरल कार्यों का मूल रूप से शामिल थे।

मेरे पास एक विशाल स्ट्रिंग सूची थी जिसे संसाधित करने की आवश्यकता थी। नोटिस listऔर string। दोनों प्रकार में पूरी तरह से मेल नहीं खाते हैं c, क्योंकि अजगर स्ट्रिंग डिफ़ॉल्ट यूनिकोड और द्वारा हैंc स्ट्रिंग्स नहीं हैं। अजगर में सूचियाँ केवल c की सरणियाँ नहीं हैं।

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

एक ही फ़ंक्शन को लागू करने के लिए दोनों में निवेश करने के लिए मुझे कितना समय चाहिए, इस पर एक विस्तृत विवरण दिया गया है। मैंने बहुत कम C / C ++ प्रोग्रामिंग को इस तरह से किया:

  • ctypes:

    • 2h के बारे में शोध करने के लिए कि कैसे यूनिकोड स्ट्रिंग्स की मेरी सूची को एसी संगत प्रकार में बदलना है।
    • एसी फ़ंक्शन से एक स्ट्रिंग को ठीक से वापस करने के बारे में एक घंटे के बारे में। यहां मैंने वास्तव में एसओ को अपने स्वयं के समाधान प्रदान किए हैं एक बार जब मैंने फ़ंक्शन लिखा है।
    • सी में कोड लिखने के लिए लगभग आधे घंटे, एक गतिशील पुस्तकालय में संकलित करें।
    • अगर cकोड काम करता है, यह जांचने के लिए अजगर में एक परीक्षण कोड लिखने के लिए 10 मिनट ।
    • कुछ परीक्षण करने और cकोड को फिर से व्यवस्थित करने के एक घंटे के बारे में ।
    • फिर मैंने cकोड को वास्तविक कोड बेस में प्लग किया , और देखा कि मॉड्यूल के ctypesसाथ अच्छा नहीं खेलता multiprocessingक्योंकि इसका हैंडलर डिफ़ॉल्ट रूप से पिक करने योग्य नहीं है।
    • लगभग 20 मिनट मैंने अपने कोड को multiprocessingमॉड्यूल का उपयोग नहीं करने के लिए पुन: व्यवस्थित किया , और वापस ले लिया।
    • फिर मेरे में दूसरा कार्य c कोड कोड बेस में segfaults उत्पन्न किया, हालांकि इसने मेरे परीक्षण कोड को पारित किया। खैर, यह शायद किनारे के मामलों के साथ अच्छी तरह से जाँच नहीं करने के लिए मेरी गलती है, मैं एक त्वरित समाधान की तलाश कर रहा था।
    • लगभग 40 मिनट के लिए मैंने इन सेगफुल्स के संभावित कारणों को निर्धारित करने की कोशिश की।
    • मैंने अपने कार्यों को दो पुस्तकालयों में विभाजित किया और फिर से प्रयास किया। अभी भी मेरे दूसरे समारोह के लिए segfaults था।
    • मैंने दूसरे समारोह में जाने का फैसला किया और cकोड के केवल पहले फ़ंक्शन का उपयोग किया और पायथन लूप के दूसरे या तीसरे पुनरावृत्ति पर जो इसका उपयोग करता है, मुझे UnicodeErrorकुछ स्थिति में एक बाइट को डिकोडिंग नहीं करने के बारे में था, हालांकि मैंने एन्कोड किया और कभी भी कुछ भी नहीं किया। स्पष्ट रूप।

इस बिंदु पर, मैंने एक विकल्प की तलाश करने का फैसला किया और इस पर गौर करने का फैसला किया cython:

  • Cython
    • साइथन हैलो दुनिया पढ़ने के 10 मिनट
    • इसके बजाय साइथॉन का उपयोग करने के बारे में एसओ की जाँच के 15 मिनट ।setuptoolsdistutils
    • साइथन प्रकार और अजगर प्रकार पर पढ़ने के 10 मिनट । मैंने सीखा कि मैं स्थैतिक टाइपिंग के लिए अधिकांश बिलियन पायथन प्रकारों का उपयोग कर सकता हूं।
    • साइथन प्रकार के साथ मेरे अजगर कोड reannotating के 15 मिनट।
    • setup.pyमेरे कोडबेस में संकलित मॉड्यूल का उपयोग करने के लिए मुझे संशोधित करने के 10 मिनट ।
    • multiprocessingकोडबेस के संस्करण में सीधे मॉड्यूल में प्लग किया गया । यह काम करता हैं।

निश्चित रूप से, रिकॉर्ड के लिए, मैंने अपने निवेश की सही समयसीमा नहीं मापी। यह बहुत अच्छी तरह से मामला हो सकता है कि समय की मेरी धारणा मानसिक प्रयासों के कारण थोड़ी सी चौकस थी, जबकि मैं cypypes के साथ काम कर रहा था। लेकिन इससे निपटने की भावना व्यक्त करनी चाहिए cythonऔरctypes

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.