NumPy 1.14 - is_array()

numpy.i: NumPy के लिए एक SWIG इंटरफ़ेस फ़ाइल




numpy

numpy.i: NumPy के लिए एक SWIG इंटरफ़ेस फ़ाइल

परिचय

सिंपल रैपर और इंटरफेस जेनरेटर (या SWIG ) विभिन्न प्रकार की स्क्रिप्टिंग भाषाओं के लिए रैपर कोड बनाने के लिए एक शक्तिशाली उपकरण है। SWIG हेडर फ़ाइलों को पार्स कर सकता है, और केवल कोड प्रोटोटाइप का उपयोग करके, लक्ष्य भाषा के लिए एक इंटरफ़ेस बना सकता है। लेकिन SWIG सर्वशक्तिमान नहीं है। उदाहरण के लिए, इसे प्रोटोटाइप से नहीं जाना जा सकता है:

double rms(double* seq, int n);

वास्तव में seq क्या है। क्या जगह में बदलाव होना एक मूल्य है? क्या यह एक सरणी है, और यदि इसकी लंबाई क्या है? क्या यह केवल इनपुट है? केवल उत्पादन-? इनपुट आउटपुट? SWIG इन विवरणों को निर्धारित नहीं कर सकता है, और ऐसा करने का प्रयास नहीं करता है।

यदि हमने rms डिज़ाइन किया है, तो हमने संभवतः इसे एक रूटीन बनाया है जो seq नामक double मानों की लंबाई n का इनपुट-केवल सरणी लेता है और रूट माध्य वर्ग लौटाता है। SWIG का डिफ़ॉल्ट व्यवहार, हालांकि, एक रैपर फ़ंक्शन का निर्माण करेगा, जो संकलित करता है, लेकिन स्क्रिप्टिंग भाषा से उस तरह का उपयोग करना असंभव है जिस तरह से सी दिनचर्या का उद्देश्य था।

पायथन के लिए, सजातीय डेटा के सन्निहित (या तकनीकी रूप से, तार ) को संभालने का पसंदीदा तरीका NumPy के साथ है, जो डेटा के बहु-विषयक सरणियों को पूर्ण ऑब्जेक्ट-ओरिएंटेड एक्सेस प्रदान करता है। इसलिए, rms फ़ंक्शन के लिए सबसे तार्किक पायथन इंटरफ़ेस (डॉक स्ट्रिंग सहित) होगा:

def rms(seq):
    """
    rms: return the root mean square of a sequence
    rms(numpy.ndarray) -> double
    rms(list) -> double
    rms(tuple) -> double
    """

जहां seq double मानों की संख्या होगी, और C रूटीन में पास होने से पहले इसकी लंबाई n seq आंतरिक रूप से निकाली जाएगी। इससे भी बेहतर, चूंकि NumPy मनमाने ढंग से पायथन क्रमों से सरणियों के निर्माण का समर्थन करता है, seq अपने आप में लगभग मनमाना अनुक्रम हो सकता है (इसलिए जब तक कि प्रत्येक तत्व को एक double बदला जा सकता है) और आवरण कोड आंतरिक रूप से इसे निकालने से पहले एक NumPy सरणी में बदल देगा। डेटा और लंबाई।

SWIG इन प्रकार के रूपांतरणों को टाइपमैप नामक एक तंत्र के माध्यम से परिभाषित करने की अनुमति देता है। यह दस्तावेज़ numpy.i का उपयोग करने के तरीके के बारे में जानकारी प्रदान करता है, जो एक SWIG इंटरफ़ेस फ़ाइल है, जिसे लागू करने के लिए सरल से ऊपर वर्णित सरणी-संबंधित रूपांतरण के प्रकार को बनाने के उद्देश्य से numpy.i एक श्रृंखला को परिभाषित करता है। उदाहरण के लिए, मान लें कि ऊपर परिभाषित किया गया rms फ़ंक्शन प्रोटोटाइप rms.h नामक हेडर फ़ाइल में था। ऊपर चर्चा किए गए पायथन इंटरफ़ेस को प्राप्त करने के लिए, आपकी SWIG इंटरफ़ेस फ़ाइल को निम्नलिखित की आवश्यकता होगी:

%{
#define SWIG_FILE_WITH_INIT
#include "rms.h"
%}

%include "numpy.i"

%init %{
import_array();
%}

%apply (double* IN_ARRAY1, int DIM1) {(double* seq, int n)};
%include "rms.h"

टाइपमैप को एक या अधिक फ़ंक्शन तर्कों की सूची से टाइप किया जाता है, या तो टाइप या नाम से। हम हस्ताक्षर के रूप में ऐसी सूचियों का उल्लेख करेंगे। numpy.i द्वारा परिभाषित कई numpy.i एक का उपयोग ऊपर किया गया है और इसमें हस्ताक्षर (double* IN_ARRAY1, int DIM1) । तर्क नामों का सुझाव है कि double* तर्क एक आयाम का एक इनपुट सरणी है और यह कि int उस आयाम के आकार का प्रतिनिधित्व करता है। यह rms प्रोटोटाइप में ठीक पैटर्न है।

सबसे अधिक संभावना है, लिपटे जाने वाले कोई वास्तविक प्रोटोटाइप में IN_ARRAY1 और DIM1 के तर्क नाम नहीं DIM1 । हम SWIG %apply उपयोग rms द्वारा उपयोग किए जाने वाले वास्तविक प्रोटोटाइप में टाइप double एक-आयामी इनपुट सरणियों के लिए टाइपमेप को लागू %apply निर्देश का उपयोग करते हैं। इसलिए, प्रभावी ढंग से numpy.i का उपयोग करना, यह जानना आवश्यक है कि numpy.i क्या उपलब्ध हैं और वे क्या करते हैं।

एक SWIG इंटरफ़ेस फ़ाइल जिसमें ऊपर दिए गए SWIG निर्देश शामिल हैं, कुछ ऐसा दिखने वाला आवरण कोड उत्पन्न करेगा:

 1 PyObject *_wrap_rms(PyObject *args) {
 2   PyObject *resultobj = 0;
 3   double *arg1 = (double *) 0 ;
 4   int arg2 ;
 5   double result;
 6   PyArrayObject *array1 = NULL ;
 7   int is_new_object1 = 0 ;
 8   PyObject * obj0 = 0 ;
 9
10   if (!PyArg_ParseTuple(args,(char *)"O:rms",&obj0)) SWIG_fail;
11   {
12     array1 = obj_to_array_contiguous_allow_conversion(
13                  obj0, NPY_DOUBLE, &is_new_object1);
14     npy_intp size[1] = {
15       -1
16     };
17     if (!array1 || !require_dimensions(array1, 1) ||
18         !require_size(array1, size, 1)) SWIG_fail;
19     arg1 = (double*) array1->data;
20     arg2 = (int) array1->dimensions[0];
21   }
22   result = (double)rms(arg1,arg2);
23   resultobj = SWIG_From_double((double)(result));
24   {
25     if (is_new_object1 && array1) Py_DECREF(array1);
26   }
27   return resultobj;
28 fail:
29   {
30     if (is_new_object1 && array1) Py_DECREF(array1);
31   }
32   return NULL;
33 }

numpy.i से numpy.i कोड की निम्नलिखित पंक्तियों के लिए ज़िम्मेदार हैं: 12–20, 25 और 30. लाइन 10 rms फ़ंक्शन के इनपुट को पार्स करता है। प्रारूप स्ट्रिंग "O:rms" , हम देख सकते हैं कि तर्क सूची में एकल पायथन ऑब्जेक्ट (बृहदान्त्र से पहले O द्वारा निर्दिष्ट) होने की उम्मीद है और जिसका सूचक obj0 में संग्रहीत है। numpy.i द्वारा आपूर्ति किए गए कई कार्यों को एक सामान्य पायथन ऑब्जेक्ट से एक NumPy सरणी में रूपांतरण (संभव) रूपांतरण बनाने और जांचने के लिए कहा जाता है। इन कार्यों को अनुभाग सहायक कार्यों में समझाया गया है, लेकिन उम्मीद है कि उनके नाम स्वयं व्याख्यात्मक हैं। 12 पंक्ति में हम एक obj0 सरणी का निर्माण करने के लिए obj0 का उपयोग करते हैं। लाइन 17 पर, हम परिणाम की वैधता की जांच करते हैं: कि यह गैर-अशक्त है और इसकी मनमानी लंबाई का एक ही आयाम है। एक बार इन अवस्थाओं का सत्यापन हो जाने के बाद, हम 19 और 20 की लाइनों में डेटा बफर और लंबाई को निकालते हैं ताकि हम अंतर्निहित C फ़ंक्शन को लाइन 22 पर कॉल कर सकें। लाइन 25 उस मामले के लिए मेमोरी प्रबंधन करता है जहां हमने एक नया सरणी बनाया है जो अब नहीं है जरूरत है।

इस कोड में त्रुटि से निपटने की महत्वपूर्ण मात्रा है। ध्यान दें कि SWIG_fail goto fail लिए एक मैक्रो है, जो लाइन 28 पर लेबल का संदर्भ देता है। यदि उपयोगकर्ता गलत संख्या में तर्क प्रदान करता है, तो यह लाइन 10. पर पकड़ा जाएगा। यदि NumPy सरणी का निर्माण विफल हो जाता है या गलत के साथ एक सरणी बनाता है। आयामों की संख्या, इन त्रुटियों को लाइन 17 पर पकड़ा जाता है। और अंत में, यदि एक त्रुटि का पता लगाया जाता है, तो स्मृति को अभी भी लाइन 30 पर सही ढंग से प्रबंधित किया जाता है।

ध्यान दें कि यदि C फ़ंक्शन हस्ताक्षर एक अलग क्रम में था:

double rms(int n, double* seq);

कि SWIG rms लिए तर्क सूची के साथ ऊपर दिए गए टाइपमैप हस्ताक्षर से मेल नहीं खाएगा। सौभाग्य से, numpy.i में पिछले दिए गए डेटा पॉइंटर के साथ numpy.i का एक सेट है:

%apply (int DIM1, double* IN_ARRAY1) {(int n, double* seq)};

यह बस ऊपर उत्पन्न कोड के लाइनों 3 और 4 में arg1 और arg2 की परिभाषाओं को स्विच करने का प्रभाव है, और 19 और 20 लाइनों में उनके असाइनमेंट हैं।

Numpy.i का उपयोग करना

numpy.i फ़ाइल वर्तमान में tools/swig उप-निर्देशिका में numpy स्थापना निर्देशिका के अंतर्गत स्थित है। आमतौर पर, आप इसे उस निर्देशिका में कॉपी करना चाहेंगे जहां आप अपने रैपर विकसित कर रहे हैं।

एक साधारण मॉड्यूल जो केवल एक SWIG इंटरफ़ेस फ़ाइल का उपयोग करता है, उसमें निम्नलिखित शामिल होने चाहिए:

%{
#define SWIG_FILE_WITH_INIT
%}
%include "numpy.i"
%init %{
import_array();
%}

एक संकलित पायथन मॉड्यूल के भीतर, import_array() को केवल एक बार कॉल किया जाना चाहिए। यह एक C / C ++ फ़ाइल में हो सकता है जिसे आपने लिखा है और मॉड्यूल से जुड़ा हुआ है। यदि यह स्थिति है, तो आपकी किसी भी इंटरफ़ेस फ़ाइल में #define SWIG_FILE_WITH_INIT या import_array() कॉल नहीं करना चाहिए। या, यह इनिशियलाइज़ेशन कॉल इंटरफ़ेस फ़ाइल से SWIG द्वारा उत्पन्न रैपर फ़ाइल में हो सकता है जिसमें ऊपर के रूप में %init ब्लॉक है। यदि यह मामला है, और आपके पास एक से अधिक SWIG इंटरफ़ेस फ़ाइल है, तो केवल एक इंटरफ़ेस फ़ाइल में #define SWIG_FILE_WITH_INIT होनी चाहिए और import_array() कॉल करें।

उपलब्ध टाइपमैप्स

विभिन्न डेटा प्रकारों के सरणियों के लिए numpy.i द्वारा प्रदान किए गए टाइपमैप निर्देश, double और int , और विभिन्न प्रकार के आयाम, int या long कहते हैं, C और NumPy प्रकार के विनिर्देशों को छोड़कर एक दूसरे के समान हैं। इसलिए टाइपमेप्स को मैक्रो के माध्यम से (आमतौर पर पर्दे के पीछे) लागू किया जाता है:

%numpy_typemaps(DATA_TYPE, DATA_TYPECODE, DIM_TYPE)

जिसे उपयुक्त (DATA_TYPE, DATA_TYPECODE, DIM_TYPE) ट्रिपल के लिए लागू किया जा सकता है। उदाहरण के लिए:

%numpy_typemaps(double, NPY_DOUBLE, int)
%numpy_typemaps(int,    NPY_INT   , int)

numpy.i इंटरफ़ेस फ़ाइल निम्न C डेटा प्रकारों और %numpy_typemaps आयाम प्रकारों के लिए %numpy_typemaps को लागू करने के लिए %numpy_typemaps मैक्रो का उपयोग करती है:

  • signed char
  • unsigned char
  • short
  • unsigned short
  • int
  • unsigned int
  • long
  • unsigned long
  • long long
  • unsigned long long
  • float
  • double

निम्नलिखित विवरणों में, हम एक सामान्य DATA_TYPE संदर्भ देते हैं, जो ऊपर सूचीबद्ध C डेटा प्रकारों में से कोई भी हो सकता है, और DIM_TYPE जो कई प्रकार के पूर्णांकों में से एक होना चाहिए।

टाइपमैप के हस्ताक्षर काफी हद तक बफर पॉइंटर को दिए गए नाम पर विभेदित हैं। FARRAY साथ नाम फोरट्रान-ऑर्डर किए गए सरणियों के लिए हैं, और ARRAY नाम C- ऑर्डर किए गए (या 1D सरणियों) के लिए हैं।

इनपुट एरियर

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

1 डी:

  • ( DATA_TYPE IN_ARRAY1[ANY] )
  • ( DATA_TYPE* IN_ARRAY1, int DIM1 )
  • ( int DIM1, DATA_TYPE* IN_ARRAY1 )

2 डी:

  • ( DATA_TYPE IN_ARRAY2[ANY][ANY] )
  • ( DATA_TYPE* IN_ARRAY2, int DIM1, int DIM2 )
  • ( int DIM1, int DIM2, DATA_TYPE* IN_ARRAY2 )
  • ( DATA_TYPE* IN_FARRAY2, int DIM1, int DIM2 )
  • ( int DIM1, int DIM2, DATA_TYPE* IN_FARRAY2 )

3 डी:

  • ( DATA_TYPE IN_ARRAY3[ANY][ANY][ANY] )
  • ( DATA_TYPE* IN_ARRAY3, int DIM1, int DIM2, int DIM3 )
  • ( int DIM1, int DIM2, int DIM3, DATA_TYPE* IN_ARRAY3 )
  • ( DATA_TYPE* IN_FARRAY3, int DIM1, int DIM2, int DIM3 )
  • ( int DIM1, int DIM2, int DIM3, DATA_TYPE* IN_FARRAY3 )

4D:

  • (DATA_TYPE IN_ARRAY4[ANY][ANY][ANY][ANY])
  • (DATA_TYPE* IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4)
  • (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, , DIM_TYPE DIM4, DATA_TYPE* IN_ARRAY4)
  • (DATA_TYPE* IN_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4)
  • (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_FARRAY4)

सूचीबद्ध पहला हस्ताक्षर, ( DATA_TYPE IN_ARRAY[ANY] ) हार्ड- ( DATA_TYPE IN_ARRAY[ANY] ) आयामों के साथ एक आयामी सरणियों के लिए है। इसी तरह, ( DATA_TYPE IN_ARRAY2[ANY][ANY] ) हार्ड-कोडित आयामों के साथ दो आयामी सरणियों के लिए है, और इसी तरह तीन-आयामी के लिए।

इन-प्लेस एरे

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

1 डी:

  • ( DATA_TYPE INPLACE_ARRAY1[ANY] )
  • ( DATA_TYPE* INPLACE_ARRAY1, int DIM1 )
  • ( int DIM1, DATA_TYPE* INPLACE_ARRAY1 )

2 डी:

  • ( DATA_TYPE INPLACE_ARRAY2[ANY][ANY] )
  • ( DATA_TYPE* INPLACE_ARRAY2, int DIM1, int DIM2 )
  • ( int DIM1, int DIM2, DATA_TYPE* INPLACE_ARRAY2 )
  • ( DATA_TYPE* INPLACE_FARRAY2, int DIM1, int DIM2 )
  • ( int DIM1, int DIM2, DATA_TYPE* INPLACE_FARRAY2 )

3 डी:

  • ( DATA_TYPE INPLACE_ARRAY3[ANY][ANY][ANY] )
  • ( DATA_TYPE* INPLACE_ARRAY3, int DIM1, int DIM2, int DIM3 )
  • ( int DIM1, int DIM2, int DIM3, DATA_TYPE* INPLACE_ARRAY3 )
  • ( DATA_TYPE* INPLACE_FARRAY3, int DIM1, int DIM2, int DIM3 )
  • ( int DIM1, int DIM2, int DIM3, DATA_TYPE* INPLACE_FARRAY3 )

4D:

  • (DATA_TYPE INPLACE_ARRAY4[ANY][ANY][ANY][ANY])
  • (DATA_TYPE* INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4)
  • (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, , DIM_TYPE DIM4, DATA_TYPE* INPLACE_ARRAY4)
  • (DATA_TYPE* INPLACE_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4)
  • (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* INPLACE_FARRAY4)

ये टाइपमैप अब यह सुनिश्चित करने के लिए INPLACE_ARRAY कि INPLACE_ARRAY तर्क मूल बाइट ऑर्डर का उपयोग करते हैं। यदि नहीं, तो एक अपवाद उठाया जाता है।

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

एन डी:

  • (DATA_TYPE* INPLACE_ARRAY_FLAT, DIM_TYPE DIM_FLAT)

अर्गाउट अर्रेज़

Argout सरणियाँ सरणियाँ हैं जो C में इनपुट तर्कों में दिखाई देती हैं, लेकिन वास्तव में आउटपुट सरणियों में होती हैं। यह पैटर्न अक्सर तब होता है जब एक से अधिक आउटपुट चर होते हैं और एकल वापसी तर्क इसलिए पर्याप्त नहीं है। पायथन में, कई तर्कों को वापस करने का पारंपरिक तरीका उन्हें एक अनुक्रम (टपल, सूची, आदि) में पैक करना है और अनुक्रम को वापस करना है। यह वही है जो argout टाइपमैप करते हैं। यदि कोई लिपटे फ़ंक्शन जो इन argout टाइपमैप्स का उपयोग करता है, में एक से अधिक रिटर्न तर्क हैं, तो उन्हें पायथन के संस्करण के आधार पर एक टुपल या सूची में पैक किया जाता है। पायथन उपयोगकर्ता इन सरणियों को पास नहीं करता है, वे बस वापस आ जाते हैं। उस मामले के लिए जहां एक आयाम निर्दिष्ट किया गया है, अजगर उपयोगकर्ता को एक तर्क के रूप में उस आयाम को प्रदान करना होगा। अर्गाउट हस्ताक्षर हैं

1 डी:

  • ( DATA_TYPE ARGOUT_ARRAY1[ANY] )
  • ( DATA_TYPE* ARGOUT_ARRAY1, int DIM1 )
  • ( int DIM1, DATA_TYPE* ARGOUT_ARRAY1 )

2 डी:

  • ( DATA_TYPE ARGOUT_ARRAY2[ANY][ANY] )

3 डी:

  • ( DATA_TYPE ARGOUT_ARRAY3[ANY][ANY][ANY] )

4D:

  • ( DATA_TYPE ARGOUT_ARRAY4[ANY][ANY][ANY][ANY] )

ये आमतौर पर उन परिस्थितियों में उपयोग किए जाते हैं जहां C / C ++ में, आप ढेर पर (n) सरणी (ओं) को आवंटित करेंगे, और सरणी (एस) मानों को भरने के लिए फ़ंक्शन को कॉल करेंगे। पायथन में, एरे को आपके लिए आवंटित किया गया है और नए सरणी ऑब्जेक्ट के रूप में लौटाया गया है।

ध्यान दें कि हम 1D में DATA_TYPE* argout टाइपमैप का समर्थन करते हैं, लेकिन 2D या 3D का नहीं। यह SWIG टाइपमैप सिंटैक्स के साथ एक विचित्रता के कारण है और इसे टाला नहीं जा सकता है। ध्यान दें कि इस प्रकार के 1 डी टाइपमैप्स के लिए, पायथन फ़ंक्शन DIM1 प्रतिनिधित्व करने वाला एकल तर्क DIM1

Argout View Arrays

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

Argoutview सरणियों के लिए लिपटे जाने वाले C कोड को पॉइंटर्स द्वारा इंगित किया जाता है: डेटा को आयाम और डबल पॉइंटर्स को इंगित करता है, ताकि इन मानों को उपयोगकर्ता को वापस भेजा जा सके। इसलिए argoutview टाइपमैप हस्ताक्षर हैं

1 डी:

  • ( DATA_TYPE** ARGOUTVIEW_ARRAY1, DIM_TYPE* DIM1 )
  • ( DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEW_ARRAY1 )

2 डी:

  • ( DATA_TYPE** ARGOUTVIEW_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2 )
  • ( DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_ARRAY2 )
  • ( DATA_TYPE** ARGOUTVIEW_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2 )
  • ( DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_FARRAY2 )

3 डी:

  • ( DATA_TYPE** ARGOUTVIEW_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3)
  • ( DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_ARRAY3)
  • ( DATA_TYPE** ARGOUTVIEW_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3)
  • ( DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_FARRAY3)

4D:

  • (DATA_TYPE** ARGOUTVIEW_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4)
  • (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEW_ARRAY4)
  • (DATA_TYPE** ARGOUTVIEW_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4)
  • (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEW_FARRAY4)

ध्यान दें कि हार्ड-कोडेड आयामों के साथ सरणियाँ समर्थित नहीं हैं। ये इन टाइपमैप के दोहरे सूचक हस्ताक्षर का पालन नहीं कर सकते हैं।

मेमोरी प्रबंधित Argout देखें Arrays

numpy.i लिए एक हालिया जोड़ numpy.i जो अनुमति देता है argout सरणियों को स्मृति में विचारों के साथ प्रबंधित किया जाता है। यहां देखें चर्चा

1 डी:

  • (DATA_TYPE** ARGOUTVIEWM_ARRAY1, DIM_TYPE* DIM1)
  • (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEWM_ARRAY1)

2 डी:

  • (DATA_TYPE** ARGOUTVIEWM_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2)
  • (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEWM_ARRAY2)
  • (DATA_TYPE** ARGOUTVIEWM_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2)
  • (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEWM_FARRAY2)

3 डी:

  • (DATA_TYPE** ARGOUTVIEWM_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3)
  • (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEWM_ARRAY3)
  • (DATA_TYPE** ARGOUTVIEWM_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3)
  • (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEWM_FARRAY3)

4D:

  • (DATA_TYPE** ARGOUTVIEWM_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4)
  • (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEWM_ARRAY4)
  • (DATA_TYPE** ARGOUTVIEWM_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4)
  • (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEWM_FARRAY4)

आउटपुट एरर्स

numpy.i इंटरफ़ेस फ़ाइल कई कारणों से आउटपुट सरणियों के लिए numpy.i समर्थन नहीं करती है। सबसे पहले, C / C ++ रिटर्न तर्क एकल मान तक सीमित हैं। यह सामान्य तरीके से आयाम जानकारी प्राप्त करने से रोकता है। दूसरा, हार्ड-कोडेड लंबाई वाले सरणियों को वापसी तर्क के रूप में अनुमति नहीं है। दूसरे शब्दों में:

double[3] newVector(double x, double y, double z);

कानूनी C / C ++ सिंटैक्स नहीं है। इसलिए, हम फॉर्म का टाइपमैप प्रदान नहीं कर सकते हैं:

%typemap(out) (TYPE[ANY]);

यदि आप ऐसी स्थिति में भाग लेते हैं जहां कोई फ़ंक्शन या विधि किसी सरणी में सूचक को लौटा रही है, तो आपकी सबसे अच्छी शर्त यह है कि फ़ंक्शन के अपने संस्करण को लपेटा जाए, या तो %extend साथ वर्ग विधियों के मामले में %extend या %ignore और %rename कार्यों के मामले के लिए %rename

अन्य सामान्य प्रकार: बूल

ध्यान दें कि उपलब्ध टाइपमैप अनुभाग में C ++ टाइप bool सूची में समर्थित नहीं है। NumPy बूल एक एकल बाइट हैं, जबकि C ++ bool चार बाइट्स (कम से कम मेरे सिस्टम पर) हैं। इसलिए:

%numpy_typemaps(bool, NPY_BOOL, int)

टाइपमैप्स में परिणाम होगा कि अनुचित डेटा लंबाई संदर्भ कोड का उत्पादन होगा। आप निम्नलिखित मैक्रो विस्तार को लागू कर सकते हैं:

%numpy_typemaps(bool, NPY_UINT, int)

डेटा की लंबाई की समस्या को ठीक करने के लिए, और इनपुट ऐरे ठीक काम करेंगे, लेकिन इन-प्लेस एरर टाइप-चेकिंग विफल हो सकते हैं।

अन्य सामान्य प्रकार: जटिल

जटिल फ़्लोटिंग-पॉइंट प्रकारों के लिए टाइपमैप रूपांतरण भी स्वचालित रूप से समर्थित नहीं है। ऐसा इसलिए है क्योंकि पायथन और न्यूमपी सी में लिखे गए हैं, जिनमें मूल जटिल प्रकार नहीं हैं। पायथन और न्यूपे दोनों जटिल चरों के लिए अपनी (अनिवार्य रूप से समतुल्य) struct परिभाषाओं को लागू करते हैं:

/* Python */
typedef struct {double real; double imag;} Py_complex;

/* NumPy */
typedef struct {float  real, imag;} npy_cfloat;
typedef struct {double real, imag;} npy_cdouble;

हम लागू कर सकते हैं:

%numpy_typemaps(Py_complex , NPY_CDOUBLE, int)
%numpy_typemaps(npy_cfloat , NPY_CFLOAT , int)
%numpy_typemaps(npy_cdouble, NPY_CDOUBLE, int)

जो Py_complex , npy_cfloat और npy_cdouble प्रकार के सरणियों के लिए स्वचालित प्रकार रूपांतरण प्रदान npy_cdouble । हालाँकि, ऐसा नहीं लगता था कि कोई स्वतंत्र (नॉन-पायथन, नॉन-न्यूपी) एप्लीकेशन कोड होगा जिसे लोग पायथन इंटरफ़ेस बनाने के लिए SWIG का उपयोग कर रहे होंगे, जिसने जटिल प्रकारों के लिए इन परिभाषाओं का भी उपयोग किया। अधिक संभावना है, ये एप्लिकेशन कोड अपने स्वयं के जटिल प्रकारों को परिभाषित करेंगे, या C ++ के मामले में, std::complex उपयोग करेंगे। मान लें कि ये डेटा संरचनाएं Python और NumPy जटिल प्रकारों के साथ संगत हैं, तो ऊपर के रूप में %numpy_typemap विस्तार (पहले तर्क के लिए प्रतिस्थापित उपयोगकर्ता के जटिल प्रकार) के साथ काम करना चाहिए।

NumPy ऐरे स्केलर और SWIG

SWIG में संख्यात्मक प्रकारों के लिए परिष्कृत प्रकार की जाँच है। उदाहरण के लिए, यदि आपका C / C ++ रूटीन इनपुट के रूप में पूर्णांक की अपेक्षा करता है, तो SWIG द्वारा उत्पन्न कोड पायथन पूर्णांक और पायथन दोनों के पूर्णांकों के लिए जाँच करेगा, और एक अतिप्रवाह त्रुटि को बढ़ाएगा यदि प्रदान किया गया पायथन पूर्णांक C को नीचे लाने के लिए बहुत बड़ा है। पूर्णांक। अपने Python कोड में NumPy स्केलर सरणियों की शुरूआत के साथ, आप संभवतः एक NumPy सरणी से पूर्णांक निकाल सकते हैं और इसे एक SWIG- क्रॉप्ड C / C ++ फ़ंक्शन में पास करने का प्रयास करते हैं जो एक int अपेक्षा करता है, लेकिन SWIG प्रकार की जाँच पहचान नहीं करेगा। एक पूर्णांक के रूप में NumPy सरणी स्केलर। (अक्सर, यह वास्तव में काम करता है - यह इस बात पर निर्भर करता है कि आपके द्वारा उपयोग किए जा रहे प्लेटफ़ॉर्म पर पायथन पूर्णांक प्रकार से विरासत में मिलने वाले पूर्णांक प्रकार को NumPy पहचानता है या नहीं। कभी-कभी, इसका मतलब यह है कि कोड 32-बिट मशीन पर काम करता है। 64-बिट मशीन पर विफल।)

यदि आपको एक पायथन त्रुटि मिलती है जो निम्न की तरह दिखाई देती है:

TypeError: in method 'MyClass_MyMethod', argument 2 of type 'int'

और आप जो तर्क पारित कर रहे हैं, वह एक पूर्णांक है जिसे एक न्यूपी सरणी से निकाला जाता है, तब आपने इस समस्या पर ठोकर खाई है। समाधान मानक पूर्णांक प्रकारों के अलावा, NumPy सरणी स्केलरों को स्वीकार करने के लिए SWIG प्रकार रूपांतरण प्रणाली को संशोधित करना है। सौभाग्य से, यह क्षमता आपके लिए प्रदान की गई है। बस फ़ाइल की प्रतिलिपि बनाएँ:

pyfragments.swg

आप के लिए काम कर निर्माण निर्देशिका, और इस समस्या को ठीक किया जाएगा। यह सुझाव दिया जाता है कि आप इसे वैसे भी करते हैं, क्योंकि यह केवल आपके पायथन इंटरफ़ेस की क्षमताओं को बढ़ाता है।

क्यों एक दूसरी फ़ाइल है?

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

एक पायथन पूर्णांक को C C में परिवर्तित करने के लिए एक अंश है। एक अलग टुकड़ा है जो एक पायनियर पूर्णांक को C int परिवर्तित करता है, जो long खंड में परिभाषित दिनचर्या को कहता है। हम long खंड के लिए परिभाषा को बदलकर यहां अपने इच्छित बदलाव कर long हैं। SWIG एक "पहले आओ, पहले पाओ" प्रणाली का उपयोग करके एक टुकड़े के लिए सक्रिय परिभाषा निर्धारित करता है। यही है, हमें SWIG को आंतरिक रूप से करने से पहले long रूपांतरण के लिए खंड को परिभाषित करने की आवश्यकता है। SWIG फ़ाइल pyfragments.swg में हमारी खंड परिभाषाएँ डालकर हमें ऐसा करने की अनुमति देता है। अगर हम नई टुकड़े परिभाषाओं को numpy.i में numpy.i , तो उन्हें नजरअंदाज कर दिया जाएगा।

हेल्पर कार्य

numpy.i फ़ाइल में कई मैक्रो और रूटीन होते हैं जो अपने टाइपमैप को बनाने के लिए आंतरिक रूप से उपयोग करते हैं। हालाँकि, ये फ़ंक्शन आपकी इंटरफ़ेस फ़ाइल में कहीं और उपयोगी हो सकते हैं। इन मैक्रो और रूटीन को टुकड़े के रूप में लागू किया जाता है, जिन्हें पिछले अनुभाग में संक्षेप में वर्णित किया गया है। यदि आप निम्नलिखित मैक्रोज़ या फ़ंक्शंस में से एक या अधिक का उपयोग करने का प्रयास करते हैं, लेकिन आपके कंपाइलर को शिकायत है कि यह प्रतीक को नहीं पहचानता है, तो आपको इन टुकड़ों को अपने कोड में उपयोग करने के लिए बाध्य करने की आवश्यकता है:

%fragment("NumPy_Fragments");

अपने SWIG इंटरफ़ेस फ़ाइल में।

मैक्रो

is_array (क)
सच के रूप में मूल्यांकन यदि a गैर-पूर्ण NULL और एक PyArrayObject* लिए डाला जा सकता है।
array_type (क)
पूर्णांक डेटा प्रकार कोड का मूल्यांकन करता a , यह मानते हुए a इसे PyArrayObject* डाला जा सकता है।
array_numdims (क)
पूर्णांक संख्या के आयामों का मूल्यांकन करता a , मान सकता है कि एक PyArrayObject* को कास्ट किया जा सकता है।
array_dimensions (क)
प्रकार के npy_intp और लंबाई array_numdims(a) एक सरणी का मूल्यांकन करता है, array_numdims(a) के सभी आयामों की लंबाई देते हुए, माना जा सकता है कि PyArrayObject* को कास्ट किया जा सकता है।
ARRAY_SIZE (एक, मैं)
के i -th आयाम आकार का मूल्यांकन करता a , मान सकता है कि एक PyArrayObject* को कास्ट किया जा सकता है।
array_strides (क)
एक प्रकार के npy_intp और लंबाई array_numdims(a) एक सरणी का मूल्यांकन करता है, a के सभी आयामों की पूर्णता देते हुए, माना जा सकता है कि PyArrayObject* को कास्ट किया जा सकता है। एक स्ट्राइड एक तत्व और उसके तत्काल पड़ोसी के बीच बाइट्स में एक ही धुरी के साथ दूरी है।
array_stride (एक, मैं)
के i -th स्ट्राइड का मूल्यांकन a , मान सकता है कि एक PyArrayObject* को कास्ट किया जा सकता है।
array_data (क)
एक प्रकार के void* सूचक का मूल्यांकन करता है void* जो डेटा के बफर को इंगित a , यह मानते हुए a इसे PyArrayObject* डाला जा सकता है।
array_descr (क)
एक की dtype संपत्ति ( PyArray_Descr* ) के लिए एक उधार संदर्भ देता है, यह मानते हुए कि एक PyArrayObject* को कास्ट किया जा सकता है।
array_flags (क)
एक पूर्णांक के झंडे का प्रतिनिधित्व करने वाला पूर्णांक देता a , मान सकता है कि इसे PyArrayObject* डाला जा सकता है।
array_enableflags (क, च)
सेट के झंडे को f के द्वारा दर्शाया गया a , मान सकते हैं कि इसे PyArrayObject* डाला जा सकता है।
array_is_contiguous (क)
सच के रूप में मूल्यांकन करता है अगर एक सन्निहित सरणी है। (PyArray_ISCONTIGUOUS(a)) समतुल्य।
array_is_native (क)
मूल बाइट क्रम का उपयोग करता है के डेटा बफ़र सच के रूप में मूल्यांकन करता है। (PyArray_ISNOTSWAPPED(a)) बराबर
array_is_fortran (क)
सही है अगर FORTRAN का आदेश दिया गया है तो मूल्यांकन सही है।

दिनचर्या

pytype_string ()

वापसी प्रकार: const char*

तर्क:

  • PyObject* py_obj , एक सामान्य पायथन ऑब्जेक्ट।

py_obj के प्रकार का वर्णन करते हुए एक स्ट्रिंग लौटें।

typecode_string ()

वापसी प्रकार: const char*

तर्क:

  • int typecode , एक NumPy पूर्णांक टाइपबॉक्स।

NumPy typecode अनुरूप प्रकार का वर्णन करने वाली एक स्ट्रिंग लौटें।

type_match ()

वापसी प्रकार: int

तर्क:

  • int actual_type , एक NumPy सरणी का NumPy टाइप-बी।
  • int desired_type , वांछित NumPy टंकण।

सुनिश्चित करें कि actual_type के साथ संगत है। उदाहरण के लिए, यह चरित्र और बाइट प्रकार, या इंट और लंबे प्रकार को मैच करने की अनुमति देता है। यह अब PyArray_EquivTypenums() बराबर है।

obj_to_array_no_conversion ()

वापसी प्रकार: PyArrayObject*

तर्क:

  • PyObject* input , एक सामान्य पायथन ऑब्जेक्ट।
  • int typecode , वांछित न्यूपे टाइपबॉक्स।

यदि कोई कानूनी है, तो PyArrayObject* को input दें और यह सुनिश्चित करें कि यह टाइप typecode । यदि input कास्ट नहीं किया जा सकता है, या typecode गलत है, तो पायथन त्रुटि सेट करें और NULL लौटें।

obj_to_array_allow_conversion ()

वापसी प्रकार: PyArrayObject*

तर्क:

  • PyObject* input , एक सामान्य पायथन ऑब्जेक्ट।
  • int typecode , परिणामी सरणी के वांछित न्यूपे टाइपबॉक्स।
  • int* is_new_object , 0 का मान लौटाता है यदि कोई रूपांतरण नहीं किया जाता है, तो 1।

दिए गए typecode साथ एक NumPy एरे में input कन्वर्ट करें। सफलता पर, सही प्रकार के साथ एक मान्य PyArrayObject* । असफल होने पर, पायथन त्रुटि स्ट्रिंग सेट हो जाएगा और रूटीन NULL देता NULL

make_contiguous ()

वापसी प्रकार: PyArrayObject*

तर्क:

  • PyArrayObject* ary , एक PyArrayObject* ary सरणी।
  • int* is_new_object , 0 का मान लौटाता है यदि कोई रूपांतरण नहीं किया जाता है, तो 1।
  • int min_dims , न्यूनतम स्वीकार्य आयाम।
  • int max_dims , अधिकतम स्वीकार्य आयाम।

यह देखने के लिए जांचें कि क्या ary सन्निहित है। यदि हां, तो इनपुट पॉइंटर लौटाएं और इसे एक नई वस्तु के रूप में चिह्नित करें। यदि यह सन्निहित नहीं है, तो मूल डेटा का उपयोग करके एक नया PyArrayObject* बनाएं, इसे एक नई ऑब्जेक्ट के रूप में फ़्लैग करें और पॉइंटर लौटाएं।

make_fortran ()

वापसी प्रकार: PyArrayObject*

तर्क

  • PyArrayObject* ary , एक PyArrayObject* ary सरणी।
  • int* is_new_object , 0 का मान लौटाता है यदि कोई रूपांतरण नहीं किया जाता है, तो 1।

यह देखने के लिए जांचें कि ary फोरट्रान सन्निहित है या नहीं। यदि हां, तो इनपुट पॉइंटर लौटाएं और इसे एक नई वस्तु के रूप में चिह्नित करें। यदि यह फोरट्रान सन्निहित नहीं है, तो मूल डेटा का उपयोग करके एक नया PyArrayObject* बनाएं, इसे एक नई ऑब्जेक्ट के रूप में फ़्लैग करें और पॉइंटर लौटाएं।

obj_to_array_contiguous_allow_conversion ()

वापसी प्रकार: PyArrayObject*

तर्क:

  • PyObject* input , एक सामान्य पायथन ऑब्जेक्ट।
  • int typecode , परिणामी सरणी के वांछित न्यूपे टाइपबॉक्स।
  • int* is_new_object , 0 का मान लौटाता है यदि कोई रूपांतरण नहीं किया जाता है, तो 1।

निर्दिष्ट प्रकार के एक सन्निहित PyArrayObject* में input परिवर्तित करें। यदि इनपुट ऑब्जेक्ट एक सन्निहित PyArrayObject* , तो एक नया बनाया जाएगा और नया ऑब्जेक्ट ध्वज सेट किया जाएगा।

obj_to_array_fortran_allow_conversion ()

वापसी प्रकार: PyArrayObject*

तर्क:

  • PyObject* input , एक सामान्य पायथन ऑब्जेक्ट।
  • int typecode , परिणामी सरणी के वांछित न्यूपे टाइपबॉक्स।
  • int* is_new_object , 0 का मान लौटाता है यदि कोई रूपांतरण नहीं किया जाता है, तो 1।

निर्दिष्ट प्रकार के एक फोरट्रान सन्निहित PyArrayObject* में input बदलें। यदि इनपुट ऑब्जेक्ट Fortran contiguous PyArrayObject* , तो एक नया बनाया जाएगा और नया ऑब्जेक्ट फ्लैग सेट किया जाएगा।

require_contiguous ()

वापसी प्रकार: int

तर्क:

  • PyArrayObject* ary , एक PyArrayObject* ary सरणी।

परीक्षण करें कि क्या ary सन्निहित है। यदि हां, तो 1. लौटें, अन्यथा, पायथन त्रुटि सेट करें और 0 लौटें।

require_native ()

वापसी प्रकार: int

तर्क:

  • PyArray_Object* ary , एक PyArray_Object* ary सरणी।

आवश्यकता है कि ary बाइट-स्वैप नहीं है। यदि सरणी बाइट-स्वैप नहीं है, तो 1. लौटें, अन्यथा, पायथन त्रुटि सेट करें और 0 लौटें।

require_dimensions ()

वापसी प्रकार: int

तर्क:

  • PyArrayObject* ary , एक PyArrayObject* ary सरणी।
  • int exact_dimensions आयाम, आयामों की वांछित संख्या।

आयामों की एक निर्दिष्ट संख्या के लिए ary आवश्यकता है। यदि सरणी में निर्दिष्ट आयाम हैं, तो 1. लौटें, अन्यथा, पायथन त्रुटि सेट करें और 0 लौटें।

require_dimensions_n ()

वापसी प्रकार: int

तर्क:

  • PyArrayObject* ary , एक PyArrayObject* ary सरणी।
  • int* exact_dimensions , पूर्णांक की एक सरणी जो आयामों की स्वीकार्य संख्या का प्रतिनिधित्व करती है।
  • int n , exact_dimensions की लंबाई।

निर्दिष्ट आयामों की एक सूची में से एक होने के लिए ary आवश्यकता है। यदि सरणी में निर्दिष्ट आयामों में से एक है, तो 1. वापस करें, अन्यथा, पायथन त्रुटि स्ट्रिंग सेट करें और 0 लौटें।

require_size ()

वापसी प्रकार: int

तर्क:

  • PyArrayObject* ary , एक PyArrayObject* ary सरणी।
  • npy_int* size , एक सरणी जो प्रत्येक आयाम की वांछित लंबाई का प्रतिनिधित्व करता है।
  • int n , size की लंबाई।

एक निर्दिष्ट आकार के लिए ary आवश्यकता होती है। यदि सरणी में निर्दिष्ट आकार है, तो 1. वापस करें, अन्यथा, पायथन त्रुटि स्ट्रिंग सेट करें और 0 लौटें।

require_fortran ()

वापसी प्रकार: int

तर्क:

  • PyArrayObject* ary , एक PyArrayObject* ary सरणी।

दिए गए PyArrayObject को फोरट्रान का आदेश दिया जाना चाहिए। यदि PyArrayObject पहले से ही फोरट्रान का आदेश दिया है, तो कुछ भी न करें। एल्स, फोरट्रान ऑर्डरिंग फ्लैग को सेट करें और स्ट्रिप्स को फिर से खोलें।

प्रदान किए गए टाइपमैप के अलावा

कई C या C ++ सरणी / NumPy सरणी स्थितियां हैं जिन्हें एक साधारण %include "numpy.i" द्वारा कवर नहीं किया गया है, %include "numpy.i" और बाद में %apply निर्देश शामिल हैं।

एक आम उदाहरण

डॉट उत्पाद फ़ंक्शन के लिए एक उचित प्रोटोटाइप पर विचार करें:

double dot(int len, double* vec1, double* vec2);

अजगर इंटरफ़ेस जो हम चाहते हैं वह है:

def dot(vec1, vec2):
    """
    dot(PyObject,PyObject) -> double
    """

यहां समस्या यह है कि एक आयाम तर्क और दो सरणी तर्क हैं, और हमारे टाइपमैप्स उन आयामों के लिए सेट किए गए हैं जो एकल सरणी पर लागू होते हैं (वास्तव में, SWIG vec2 साथ len को vec2 लिए एक तंत्र प्रदान नहीं करता है जो दो vec2 इनपुट तर्क लेता है )। अनुशंसित समाधान निम्नलिखित है:

%apply (int DIM1, double* IN_ARRAY1) {(int len1, double* vec1),
                                      (int len2, double* vec2)}
%rename (dot) my_dot;
%exception my_dot {
    $action
    if (PyErr_Occurred()) SWIG_fail;
}
%inline %{
double my_dot(int len1, double* vec1, int len2, double* vec2) {
    if (len1 != len2) {
        PyErr_Format(PyExc_ValueError,
                     "Arrays of lengths (%d,%d) given",
                     len1, len2);
        return 0.0;
    }
    return dot(len1, vec1, vec2);
}
%}

यदि हेडर फ़ाइल जिसमें double dot() लिए प्रोटोटाइप शामिल है double dot() में अन्य प्रोटोटाइप भी शामिल हैं जिन्हें आप लपेटना चाहते हैं, ताकि आपको %include इस हेडर फ़ाइल को %include करने की आवश्यकता हो, तो आपको एक %ignore dot; की भी आवश्यकता होगी %ignore dot; %rename बाद और %rename से पहले निर्देश %include निर्देश %include । या, यदि विचाराधीन फ़ंक्शन एक वर्ग विधि है, तो आप %ignore अलावा %inline बजाय %extend का उपयोग करना चाहेंगे।

त्रुटि से निपटने पर एक नोट: ध्यान दें कि my_dot एक double रिटर्न देता है लेकिन यह पायथन त्रुटि भी बढ़ा सकता है। परिणामी आवरण समारोह 0.0 के पायथन फ्लोट प्रतिनिधित्व को लौटाएगा जब वेक्टर लंबाई मेल नहीं खाती। चूँकि यह NULL नहीं NULL , पायथन दुभाषिया को एक त्रुटि की जाँच करने के लिए नहीं पता होगा। इस कारण से, हम my_dot लिए ऊपर %exception जोड़ते हैं ताकि हम जो व्यवहार चाहते हैं (ध्यान दें कि $action एक मैक्रो है जो my_dot लिए एक वैध कॉल तक विस्तारित हो my_dot )। सामान्य तौर पर, आप संभवतः इस कार्य को करने के लिए एक SWIG मैक्रो लिखना चाहेंगे।

अन्य स्थिति

ऐसी अन्य रैपिंग स्थितियां हैं जिनमें numpy.i आपके सामने आने पर मददगार हो सकती है।

  • कुछ स्थितियों में, यह संभव है कि आप अपने प्रकार के %numpy_typemaps को लागू करने के लिए %numpy_typemaps मैक्रो का उपयोग कर सकते हैं। अन्य सामान्य प्रकार देखें : बूल या अन्य सामान्य प्रकार: उदाहरण के लिए जटिल अनुभाग। एक अन्य स्थिति यह है कि यदि आपके आयाम int अलावा अन्य प्रकार के हैं (उदाहरण के लिए long कहें):

    %numpy_typemaps(double, NPY_DOUBLE, long)
    
  • आप अपने खुद के numpy.i लिखने के लिए numpy.i में कोड का उपयोग कर सकते हैं। उदाहरण के लिए, यदि आपके पास फ़ंक्शन तर्क के रूप में पांच-आयामी सरणी है, तो आप अपनी इंटरफ़ेस फ़ाइल में उपयुक्त चार-आयामी टाइपमैप को काट और चिपका सकते हैं। चौथे आयाम के लिए संशोधन तुच्छ होगा।
  • कभी-कभी, सबसे अच्छा तरीका यह है कि आप अपनी कक्षाओं के लिए नए तरीकों को परिभाषित करने के लिए %extend का उपयोग करें (या मौजूदा वाले को PyObject* ) जो कि PyObject* (जो या तो है या PyArrayObject* परिवर्तित किया जा सकता है) को एक बफ़र को PyArrayObject* करने के बजाय। । इस मामले में, numpy.i में सहायक numpy.i बहुत उपयोगी हो सकता है।
  • टाइपमैप लिखना थोड़ा गैर-बोधपूर्ण हो सकता है। यदि आपके पास NumPy के लिए SWIG टाइपमैप लिखने के बारे में कुछ विशिष्ट प्रश्न हैं, तो numpy.i के डेवलपर्स numpy.i Numpy-discussion और numpy.i Swig-user मेल सूचियों की निगरानी करते हैं।

एक अंतिम नोट

जब आप %apply निर्देश का उपयोग करते हैं, जैसा कि आमतौर पर numpy.i का उपयोग करने के लिए आवश्यक numpy.i , तो यह तब तक प्रभावी रहेगा जब तक आप SWIG को यह नहीं बता देते कि यह नहीं होना चाहिए। यदि आप जिस फ़ंक्शन या विधियों को रैप कर रहे हैं, उनके तर्क सामान्य नाम हैं, जैसे कि length या vector , ये टाइपमैप उन स्थितियों में लागू हो सकते हैं जिनकी आप अपेक्षा नहीं करते हैं या चाहते हैं। इसलिए, एक विशिष्ट टाइपमैप के साथ किए जाने के बाद %clear निर्देश जोड़ना हमेशा एक अच्छा विचार है:

%apply (double* IN_ARRAY1, int DIM1) {(double* vector, int length)}
%include "my_header.h"
%clear (double* vector, int length);

सामान्य तौर पर, आपको इन टाइपमैप संकेतों को विशेष रूप से लक्षित करना चाहिए जहाँ आप उन्हें चाहते हैं, और फिर आपके द्वारा किए जाने के बाद उन्हें साफ़ करें।

सारांश

बॉक्स से बाहर, numpy.i प्रदान करता है जो NumPy सरणियों और C सरणियों के बीच रूपांतरण का समर्थन करते हैं:

  • यह 12 अलग-अलग स्केलर प्रकारों में से एक हो सकता है: signed char , unsigned char , short , unsigned short , int , unsigned int , long , unsigned long , long long , long long , long long unsigned long long
  • प्रत्येक डेटा प्रकार के लिए 74 विभिन्न तर्क हस्ताक्षरों का समर्थन करते हैं, जिनमें शामिल हैं:
    • एक आयामी, दो आयामी, तीन आयामी और चार आयामी सरणियों।
    • इनपुट-ओनली, इन-प्लेस, अर्गाउट, आर्गाउटव्यू, और मेमोरी एर्गोटव्यू व्यवहार प्रबंधित।
    • हार्ड-कोडेड आयाम, डेटा-बफर-तब-आयाम विनिर्देश, और आयाम-फिर डेटा-बफर विनिर्देश।
    • सी-ऑर्डरिंग ("अंतिम आयाम सबसे तेज़") या फ़ोर्ट्रान-ऑर्डरिंग ("पहला आयाम सबसे तेज़") 2 डी, 3 डी और 4 जी सरणियों के लिए समर्थन।

numpy.i इंटरफ़ेस फ़ाइल रैपर डेवलपर्स के लिए अतिरिक्त टूल भी प्रदान करती है, जिसमें शामिल हैं:

  • उपयोगकर्ता की पसंद (1) C डेटा प्रकार, (2) NumPy डेटा प्रकार (वे मिलान करते हुए), और (3) आयाम प्रकार के लिए 74 तर्क हस्ताक्षर लागू करने के लिए तीन तर्क के साथ एक SWIG मैक्रो ( %numpy_typemaps )।
  • चौदह सी मैक्रोज़ और पंद्रह सी फ़ंक्शंस जिनका उपयोग विशेष टाइपमैप, एक्सटेंशन या इनलाइन फ़ंक्शन लिखने के लिए किया जा सकता है, जो प्रदान किए गए टाइपमैप द्वारा कवर नहीं किए गए मामलों को संभालते हैं। ध्यान दें कि मैक्रोज़ और फ़ंक्शंस को विशेष रूप से NumPy C / API के साथ काम करने के लिए कोडित किया गया है, भले ही NumPy संस्करण संख्या की परवाह किए बिना, संस्करण 1.6 के बाद एपीआई के कुछ पहलुओं के अपवर्तन के पहले और बाद में दोनों।

Original text