2012-04-21 10 views
7

मैं सिर्फ अजगर सी एक्सटेंशन के साथ खेलते हैं और क्यों एक सी समारोह है, जो अजगर से प्रतिदेय है 2 PyObject रखना चाहिए के रूप में उत्सुक हूँ शुरू कर रहा हूँ * तर्क और एक PyObject * वापस करें। मैं निम्नलिखित "नमस्ते दुनिया" विस्तार लिखा है:अजगर सी एक्सटेंशन - क्यों प्रतिदेय चाहिए सी कार्यों तर्क ले और वापसी PyObject *

#include <Python.h> 

static PyObject * 
hello_world(PyObject *self, PyObject *noargs) 
{ 
    printf("Hello World\n"); 
    return Py_BuildValue(""); 
} 


// Module functions table. 

static PyMethodDef 
module_functions[] = { 
    { "hello_world", hello_world, METH_NOARGS, "hello world method" }, 
    { NULL } 
}; 


// This function is called to initialize the module. 
PyMODINIT_FUNC 
inittesty2(void) 
{ 
    Py_InitModule("testy2", module_functions); 
} 

क्यों नहीं मैं (विशेष रूप से METH_NOARGS के साथ) निम्नलिखित hello_world विधि का उपयोग करें:

static void 
hello_world() 
{ 
    printf("Hello World\n"); 
} 

?

उत्तर

10

कई चीज़ें हैं जिन्हें विभिन्न PyObject संकेत के बारे में कहने के लिए कर रहे हैं।

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

    यह भी मतलब है कि आप एक अपवाद फेंक नहीं करना चाहती जब भी, आप एक सूचक कुछ असली PyObject में लौटना चाहिए। यदि वहाँ विशेष अपने कार्य में कुछ भी नहीं लौटने के लिए माना जाता है, बस लौट Py_None (सबसे अच्छा उपयोग Py_RETURN_NONE संदर्भ गिनती सही पाने के लिए मैक्रो), या "सच" (Py_RETURN_TRUE का उपयोग)।

  2. पहला तर्क, वस्तु समारोह से, या मॉड्यूल उदाहरण यह के अंतर्गत आता है करने के लिए कहा जाता है के लिए PyObject *self अंक। ध्यान दें कि आपके द्वारा परिभाषित प्रत्येक फ़ंक्शन या तो क्लास विधि या मॉड्यूल विधि है। कोई पूरी तरह से स्वतंत्र कार्य नहीं हैं।

  3. दूसरा तर्क, समारोह तर्क (जो एक टपल या एक से अधिक तर्कों की सूची हो सकता है) के लिए PyObject *args अंक। आप यह इंगित करने में सही हैं कि कोई फ़ंक्शन जो कोई तर्क नहीं लेता है उसे — की आवश्यकता नहीं है और जहां तक ​​मैं कह सकता हूं, आप सही हैं।आपको इसे परिभाषित करने की ज़रूरत नहीं है; जब आप इसे PyMethodDef में डाल डेटा के लिए आपके द्वारा निर्धारित टाइप आप बस तुम अब भी PyCFunction को डाली इस करना होगा

    static PyObject *PyMyClass_MyFunc(PyObject *self) { 
        /* ..do something.. */ 
        Py_RETURN_TRUE; 
    } 
    

    के रूप में एक समारोह को परिभाषित कर सकते हैं, लेकिन मुझे विश्वास है कि डाली हैं, बशर्ते उसके लिए सुरक्षित है METH_NOARGS ध्वज का उपयोग करें। लेकिन संभावित जोखिमों के लिए नीचे दी गई टिप्पणियों को नोट करें।

    static PyObject *PyMyClass_Func(PyObject *self, PyObject *args, PyObject *kwds) 
    { 
        /*...*/ 
    } 
    

    तीसरा तर्क नामित के लिए प्रयोग किया जाता है, वैकल्पिक तर्क:

  4. अंत में, एक समारोह वास्तव में हो सकता है एक तीसरा तर्क इस तरह की है। इस मामले में, आपको फ़ंक्शन पॉइंटर को PyCFunction पर डालना होगा, लेकिन यदि आप विधि तालिका में अपने फ़ंक्शन के लिए सही ध्वज (METH_KEYWORDS) सेट करते हैं, तो यह भी सुरक्षित है।

+0

यह 'Py_None' है, न कि 'PyNone'। 'Py_RETURN_RONE' और' Py_RETURN_FALSE' के समान 'Py_RETURN_NONE' भी है। – yak

+0

के लिए (3), अगर मैं गलत हूं तो मुझे सही करें, लेकिन अगर कोड एक कॉलिंग सम्मेलन का उपयोग कर रहा था, जहां सभी तर्क स्टैक पर पारित होते हैं और कैली (फ़ंक्शन) उन्हें ढेर से पॉप करता है, अप्रयुक्त तर्क को हटाकर एक कारण होगा क्रैश क्योंकि पाइथन हमेशा दूसरे तर्क के रूप में NULL पास करेगा और फ़ंक्शन इसे पॉप नहीं करेगा। – yak

+0

@yak यह मेरे कोड में एक क्रैश का कारण नहीं है। – jogojapan

2

क्योंकि अजगर काम करता है, यहां तक ​​कि तुच्छ जो कि सिर्फ stdout के लिए प्रिंट, बस सी कार्यों के आसपास रैपर की तुलना में अधिक हैं।

सामान्य स्थिति में, पायथन में आत्मनिरीक्षण सुविधाओं के बारे में सोचते हैं।

>>> def hello(): 
...  print 'hello' 
... 
>>> dir(hello) 
['__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__doc__', '__format__', '__get__', '__getattribute__', '__globals__', '__hash__', '__init__', '__module__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'func_closure', 'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_name'] 

आप निश्चित रूप से एक विस्तार सुविधा है कि बस सी कार्यों लिपटे कल्पना कर सकता: एक अजगर समारोह एक पूर्ण कलियाना उद्देश्य यह है कि आप क्वेरी कर सकते हैं। SWIG की जाँच करें, जो पटकथा भाषाओं के बहुत सारे, अजगर सहित के लिए अपने लिखने एक्सटेंशन की सुविधा देता है। चूंकि यह सबसे कम आम denominator के लिए जा रहा है, यह आपको अपने hello_world जैसे फ़ंक्शन को लपेटने देगा, लेकिन निश्चित रूप से आप बहुत सारी शक्ति खो देते हैं।

4

मॉड्यूल स्तर कार्यों के लिए पहला तर्क मॉड्यूल ऑब्जेक्ट है। सी में कक्षाओं को परिभाषित करते समय (उसी PyMethodDef संरचना का उपयोग विधियों के लिए किया जाता है), पहला तर्क उदाहरण है (पायथन में self के समान)।

METH_NOARGS का उपयोग करते समय, पायथन NULL दूसरे तर्क के रूप में पास करेगा। वे इसे एक तर्क के साथ एक समारोह में डाल सकते हैं लेकिन मुझे लगता है कि उन्होंने नहीं सोचा था कि इसकी आवश्यकता है।

वापसी मूल्य समझा जाना आसान है। प्रत्येक पायथन समारोह में वापसी मूल्य होता है। यदि आप पायथन में return का स्पष्ट रूप से उपयोग नहीं करते हैं, तो फ़ंक्शन None वापस आ जाएगा।

निश्चित रूप से सी में आपको वापसी मूल्य के बारे में स्पष्ट होना चाहिए ताकि यदि आप इसका उपयोग नहीं करते हैं, तो आपको None स्वयं लौटना होगा। अजगर इस के लिए एक मैक्रो प्रदान करता है:

Py_RETURN_NONE; 

वैकल्पिक रूप से आप वैश्विक None उदाहरण अपने आप पहुंच सकता है:

Py_INCREF(Py_None); 
return Py_None; 

लेकिन मैक्रो का उपयोग करने के लिए आसान है।

आप सोच सकते हैं कि NULL लौटने से None के बराबर होना चाहिए लेकिन NULL यह इंगित करने के लिए उपयोग किया जाता है कि फ़ंक्शन ने अपवाद उठाया था।