ctypes - शुरुआत


100

मुझे एक लाइब्रेरी में अजगर को "लपेटने" का काम है। डॉक्स इस मामले में अविश्वसनीय रूप से अस्पष्ट हैं। ऐसा लगता है कि वे केवल उन्नत अजगर उपयोगकर्ताओं को ctypes को लागू करने की उम्मीद करते हैं। अच्छी तरह से मैं अजगर में एक शुरुआत कर रहा हूँ और मदद की ज़रूरत है।

कुछ कदम से कदम मदद अद्भुत होगा।

इसलिए मेरे पास मेरी सी लाइब्रेरी है। मैं क्या करूं? मैं कहाँ क्या फ़ाइलें डालूँ? मैं लाइब्रेरी को कैसे आयात करूं? मैंने पढ़ा कि पायथन को "ऑटो रैप" करने का एक तरीका हो सकता है?

(वैसे मैंने python.net पर ctypes ट्यूटोरियल किया और यह काम नहीं करता है। मतलब मैं सोच रहा हूं कि वे मान रहे हैं कि मुझे बाकी चरणों को भरने में सक्षम होना चाहिए।

वास्तव में यह त्रुटि मुझे उनके कोड से मिलती है:

File "importtest.py", line 1
   >>> from ctypes import *
   SyntaxError: invalid syntax

मैं वास्तव में इस पर कदम से कुछ कदम का उपयोग कर सकता है! धन्यवाद ~


10
क्या आपके पास >>> importtest.py? जब लोग >>> प्रत्येक पंक्ति पर कोड डालते हैं, तो यह दर्शाता है कि यह इंटरैक्टिव शेल में चलाया जा रहा है। किसी फ़ाइल से इसे चलाने के लिए, >>> (जहाँ यह दिखाई देता है वहां 3> संकेत और एक स्थान) को हटा दें ।
चिन्मय कांची

4
>>>एस टाइप न करें । जिन्हें इंटरेक्टिव शेल द्वारा मुद्रित किया जाता है और इसे आपके स्रोत फ़ाइल से बाहर छोड़ दिया जाना चाहिए।
नौचमाल 17

8
>>>.py फ़ाइल में! ओह! ऐसा पहले कभी नहीं देखा!
डेविड हेफर्नन

3
ईमानदारी से, पायथन के साथ गड़बड़ शुरू करने से पहले अजगर (कम से कम थोड़ा सा) सीखें। आप कभी भी ctypes पर एक ऐसा ट्यूटोरियल नहीं ढूंढ सकते हैं जो यह मानता हो कि आप मूल पायथन को नहीं जानते हैं।
चिन्मय कांची

3
@spentak: यदि आप मदद मांगते हैं, तो पर्याप्त जानकारी प्रदान करें। जिस कोड के बारे में आप बात कर रहे हैं उसका कम से कम अंतिम संस्करण हमें दिखाएं। उदाहरण के लिए, "लाइन 3" पर क्या है?
फ्रांसेस्को

जवाबों:


229

यहाँ एक त्वरित और गंदा ctypes ट्यूटोरियल है।

सबसे पहले, अपनी सी लाइब्रेरी लिखें। यहाँ एक सरल हैलो दुनिया उदाहरण है:

testlib.c

#include <stdio.h>

void myprint(void);

void myprint()
{
    printf("hello world\n");
}

अब इसे एक साझा पुस्तकालय के रूप में संकलित करें ( मैक फ़िक्स यहाँ पाया गया ):

$ gcc -shared -Wl,-soname,testlib -o testlib.so -fPIC testlib.c

# or... for Mac OS X 
$ gcc -shared -Wl,-install_name,testlib.so -o testlib.so -fPIC testlib.c

फिर, ctypes का उपयोग करके एक आवरण लिखें:

testlibwrapper.py

import ctypes

testlib = ctypes.CDLL('/full/path/to/testlib.so')
testlib.myprint()

अब इसे निष्पादित करें:

$ python testlibwrapper.py

और आपको आउटपुट देखना चाहिए

Hello world
$

यदि आपके पास पहले से ही एक पुस्तकालय है, तो आप ट्यूटोरियल के गैर-अजगर भाग को छोड़ सकते हैं। सुनिश्चित करें कि ctypes लाइब्रेरी को /usr/libकिसी अन्य मानक निर्देशिका में डालकर पा सकते हैं । यदि आप ऐसा करते हैं, तो आपको रैपर लिखते समय पूर्ण पथ निर्दिष्ट करने की आवश्यकता नहीं है। यदि आप ऐसा नहीं करने का चयन करते हैं, तो आपको कॉल करते समय लाइब्रेरी का पूरा मार्ग प्रदान करना होगाctypes.CDLL()

यह अधिक व्यापक ट्यूटोरियल के लिए जगह नहीं है, लेकिन यदि आप इस साइट पर विशिष्ट समस्याओं के लिए मदद मांगते हैं, तो मुझे यकीन है कि समुदाय आपकी मदद करेगा।

PS: मैं मान रहा हूं कि आप लिनक्स पर हैं क्योंकि आपने उपयोग किया है ctypes.CDLL('libc.so.6')। यदि आप दूसरे OS पर हैं, तो चीजें थोड़ी बदल सकती हैं (या काफी कम)।


1
@ चिन्मय: क्या मेरे पास विंडोज के लिए समान कोड हो सकता है और सी के बजाय, क्या आप कृपया एक दृश्य सी ++ उदाहरण प्रदान कर सकते हैं? मैं अपनी लाइब्रेरी लोड करने में सक्षम हूं, लेकिन मैं अपने कार्यों को .dll फ़ाइल से एक्सेस नहीं कर पा रहा हूं। यह हमेशा कहता है "फ़ंक्शन 'xyz' नहीं मिला"। क्या आप मुझे इसके बारे में सुझाव दे सकते हैं? चीयर्स।
Neophile

मैं विंडोज के विकास के बारे में बहुत ज्यादा नहीं जानता, लेकिन ऐसा लग रहा है कि विंडोज कुछ जीतता है, शायद यह एक अलग कॉलिंग कन्वेंशन का उपयोग करता है? शायद आप "एक्स सी" का उपयोग करके अपने सी ++ फ़ंक्शंस का निर्यात कर सकते हैं?
चिन्मय कांची

हां, मैंने ऐसा किया लेकिन अब तक कोई किस्मत नहीं।
Neophile

6
ट्यूटोरियल का पालन करने में आसान के लिए धन्यवाद जो
ctype

1
त्वरित और गंदे हमेशा सबसे अच्छे ट्यूटोरियल हैं
15

55

चिन्मय कांची का जवाब उत्कृष्ट है, लेकिन मैं एक फ़ंक्शन का एक उदाहरण चाहता था जो एक सी ++ कोड के चर / सरणियों को पारित करता है और वापस करता है। हालाँकि मैं इसे यहाँ शामिल करूँगा क्योंकि यह दूसरों के लिए उपयोगी है।

पूर्णांक को पास करना और वापस करना

एक फ़ंक्शन के लिए C ++ कोड जो पूर्णांक लेता है और एक लौटाया गया मान जोड़ता है,

extern "C" int add_one(int i)
{
    return i+1;
}

फ़ाइल के रूप में सहेजा गया test.cpp, आवश्यक बाहरी "सी" पर ध्यान दें (इसे सी कोड के लिए हटाया जा सकता है)। यह चिन्मय कांची के उत्तर के समान तर्कों के साथ g ++ का उपयोग करके संकलित किया गया है,

g++ -shared -o testlib.so -fPIC test.cpp

पायथन कोड एक ही निर्देशिका में पायथॉन स्क्रिप्ट के समान साझा लाइब्रेरी के लिए पथ संभालने load_libraryसे उपयोग करता है numpy.ctypeslib,

import numpy.ctypeslib as ctl
import ctypes

libname = 'testlib.so'
libdir = './'
lib=ctl.load_library(libname, libdir)

py_add_one = lib.add_one
py_add_one.argtypes = [ctypes.c_int]
value = 5
results = py_add_one(value)
print(results)

यह उम्मीद के मुताबिक 6 प्रिंट करता है।

किसी सरणी को पास करना और प्रिंट करना

आप सरणी के तत्व को प्रिंट करने के लिए C कोड के लिए निम्नानुसार सरणियाँ भी पास कर सकते हैं,

extern "C" void print_array(double* array, int N)
{
    for (int i=0; i<N; i++) 
        cout << i << " " << array[i] << endl;
}

जो पहले की तरह संकलित है और उसी तरह से आयात किया जाता है। इस फ़ंक्शन का उपयोग करने के लिए अतिरिक्त पायथन कोड तब होगा,

import numpy as np

py_print_array = lib.print_array
py_print_array.argtypes = [ctl.ndpointer(np.float64, 
                                         flags='aligned, c_contiguous'), 
                           ctypes.c_int]
A = np.array([1.4,2.6,3.0], dtype=np.float64)
py_print_array(A, 3)

जहां हम सरणी निर्दिष्ट करते हैं, पहले तर्क को print_array, संरेखित के Numpy सरणी के लिए सूचक के रूप में, c_contiguous 64 बिट फ्लोट और दूसरा तर्क पूर्णांक के रूप में होता है जो C कोड को Numpy सरणी में तत्वों की संख्या बताता है। इसके बाद सी कोड द्वारा इस प्रकार मुद्रित किया गया,

1.4
2.6
3.0

5
यह एक महान पूरक उत्तर है - शर्म की बात नहीं है कि दो
टिके हुए

निश्चित नहीं है कि यह बहुत स्पष्ट है, लेकिन कोड में कोई त्रुटि है। यह गायब है import numpy as np। अन्यथा यह np.float64और अन्य सामान खोजने में सक्षम नहीं है।
बेन

11

सबसे पहले: >>>आप पायथन उदाहरणों में जो कोड देखते हैं, वह यह इंगित करने का एक तरीका है कि यह पायथन कोड है। इसका उपयोग Python कोड को आउटपुट से अलग करने के लिए किया जाता है। ऐशे ही:

>>> 4+5
9

यहां हम देखते हैं कि जिस लाइन से शुरुआत होती है >>> है वह पायथन कोड होती है, और 9 में इसका परिणाम क्या होता है। ठीक यही है कि यदि आप पायथन इंटरप्रेटर को शुरू करते हैं तो यह कैसा दिखता है, इसीलिए ऐसा किया जाता है।

आप कभी भी >>>एक हिस्से में प्रवेश नहीं करते हैं.py फ़ाइल हैं।

जो आपके सिंटैक्स त्रुटि का ख्याल रखता है।

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

वे सभी लाभ और कमियां हैं।

SWIG केवल आपके C API को पायथन में उजागर करेगा। इसका मतलब है कि आपको कोई ऑब्जेक्ट या कुछ भी नहीं मिलता है, आपको ऐसा करने के लिए एक अलग पायथन फाइल बनाना होगा। हालाँकि, "wowza" नामक एक मॉड्यूल होना और "_wowza" नामक एक SWIG मॉड्यूल का होना आम है, जो C API के चारों ओर आवरण है। यह चीजों को करने का एक अच्छा और आसान तरीका है।

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

ctypes का यह लाभ है कि संकलन करने के लिए कोई C- कोड नहीं है, इसलिए किसी अन्य व्यक्ति द्वारा लिखित मानक पुस्तकालयों को लपेटने के लिए उपयोग करना बहुत अच्छा है, और पहले से ही Windows और OS X के लिए द्विआधारी संस्करणों में मौजूद है।

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