2012-02-14 14 views
75

मेरे पास एक छोटी परियोजना है जो SWIG के साथ खूबसूरती से काम करती है। विशेष रूप से, मेरे कुछ फ़ंक्शन std::vector एस लौटते हैं, जिन्हें पायथन में टुपल्स में अनुवादित किया जाता है। अब, मैं बहुत संख्यात्मक संख्या करता हूं, इसलिए सीडीआईजी को सी ++ कोड से वापस आने के बाद इन्हें नुकीले सरणी में परिवर्तित कर दिया गया है। ऐसा करने के लिए, मैं SWIG में निम्न की तरह कुछ उपयोग करता हूं।क्या SWIG की नई बिल्टिन सुविधा के साथ Pythonappend का उपयोग करने का कोई तरीका है?

%feature("pythonappend") My::Cool::Namespace::Data() const %{ if isinstance(val, tuple) : val = numpy.array(val) %} 

(वास्तव में, डाटा नामित कई कार्य, जिनमें से कुछ तैरता वापसी, जिसके कारण मैं जाँच करें कि val वास्तव में एक टपल है कर रहे हैं।) यह सिर्फ खूबसूरती से काम करता है।

लेकिन, मैं भी -builtin झंडा है कि अब उपलब्ध है का उपयोग करना चाहते हैं। इन डेटा कार्यों के लिए कॉल दुर्लभ और अधिकतर इंटरैक्टिव हैं, इसलिए उनकी धीमी गति कोई समस्या नहीं है, लेकिन अन्य धीमी लूप भी हैं जो बिल्टिन विकल्प के साथ महत्वपूर्ण रूप से बढ़ती हैं।

समस्या यह है कि जब मुझे लगता है कि झंडा उपयोग करते हैं, pythonappend सुविधा चुपचाप नजरअंदाज कर दिया जाता है। अब, डेटा फिर से एक टुपल देता है। क्या कोई रास्ता है कि मैं अभी भी numpy arrays वापस कर सकता है? मैंने टाइपमैप का उपयोग करने की कोशिश की, लेकिन यह एक विशाल गड़बड़ में बदल गया।

संपादित करें:

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

%typemap(out) std::vector<int>& { 
    npy_intp result_size = $1->size(); 
    npy_intp dims[1] = { result_size }; 
    PyArrayObject* npy_arr = (PyArrayObject*)PyArray_SimpleNew(1, dims, NPY_INT); 
    int* dat = (int*) PyArray_DATA(npy_arr); 
    for (size_t i = 0; i < result_size; ++i) { dat[i] = (*$1)[i]; } 
    $result = PyArray_Return(npy_arr); 
} 
%typemap(out) std::vector<std::vector<int> >& { 
    npy_intp result_size = $1->size(); 
    npy_intp result_size2 = (result_size>0 ? (*$1)[0].size() : 0); 
    npy_intp dims[2] = { result_size, result_size2 }; 
    PyArrayObject* npy_arr = (PyArrayObject*)PyArray_SimpleNew(2, dims, NPY_INT); 
    int* dat = (int*) PyArray_DATA(npy_arr); 
    for (size_t i = 0; i < result_size; ++i) { for (size_t j = 0; j < result_size2; ++j) { dat[i*result_size2+j] = (*$1)[i][j]; } } 
    $result = PyArray_Return(npy_arr); 
} 

संपादित करें 2:

मैं के लिए, इसी तरह की समस्याओं का उपयोग करके भी @ भिक्षु दृष्टिकोण (explained here) को हल किया जा सकता है वह नहीं है देख रहा था हालांकि।

+4

मुझे नहीं लगता कि आप टाइपमैप लिखने और सी पक्ष पर ऐसा किए बिना ऐसा कर सकते हैं, ठीक है क्योंकि -बिल्टिन उस कोड को हटा देता है जहां सामान्य रूप से पाइथोनएपेंड रखा जाता है। क्या आप निश्चित हैं-बिल्टिन बहुत तेज है (यानी आप इसका उपयोग करने के लिए प्रोफाइलिंग का नेतृत्व कर रहे थे?) मैं दो मॉड्यूल का उपयोग करने के लिए लुभाना चाहता हूं, एक के साथ-साथ एक -बिल्टिन। – Flexo

+0

मुझे आश्चर्य है कि कोई चेतावनी नहीं है कि '-बिल्टिन' पायथन अपेंड को अनदेखा करता है। मैं 'std :: vector की numpy arrays में टाइपमैपिंग की चुनौती पर नहीं हूं। मैंने प्रोफ़ाइल की, और यह मेरे इंटरफ़ेस में सबसे कष्टप्रद लूप को काफी हद तक बढ़ा दिया (ब्रेक लेने के लिए पर्याप्त समय नहीं, अक्सर प्रतीक्षा करने में बहुत लंबा)। लेकिन मुझे यह भी एहसास हुआ कि मैं इस लूप को अपने सी ++ कोड में ले जा सकता हूं - हालांकि कुछ हद तक अजीब तरह से। तो मैं इस तरह जाऊंगा। फिर भी, आपके 'दो मॉड्यूल' सुझाव दिलचस्प है, और अन्य मामलों में उपयोगी हो सकता है। – Mike

+0

क्या आपने SWIG को -Wall के साथ बुलाया था? मैंने माना कि यह उस मामले में चेतावनी देगा। – Flexo

उत्तर

6

मैं आपसे सहमत हूँ कि typemap का उपयोग कर एक छोटे से गंदा हो जाता है, लेकिन यह सही तरीके से इस कार्य को पूरा करने के लिए है। आप यह भी सही बड़ा घूँट प्रलेखन सीधे कहते हैं कि यह नहीं है कि %pythonappend-builtin के साथ असंगत है, लेकिन यह दृढ़ता से निहित है: %pythonappendअजगर प्रॉक्सी वर्ग को जोड़ता है, और अजगर प्रॉक्सी वर्ग -builtin साथ संयोजन के रूप में बिल्कुल भी मौजूद नहीं है झंडा।

इससे पहले, आप क्या कर रहे थे, एसडब्ल्यूआईजी सी ++ std::vector ऑब्जेक्ट्स को पायथन टुपल्स में परिवर्तित कर रहा था, और उसके बाद उन tuples को numpy पर वापस ले जाया गया - जहां उन्हें फिर से परिवर्तित किया गया।

क्या तुम सच में क्या करना चाहते हैं उन्हें एक बार में परिवर्तित, सी स्तर पर है।

%{ 
#include "numpy/arrayobject.h" 
%} 

%init %{ 
    import_array(); 
%} 

%typemap(out) std::vector<int> { 
    npy_intp result_size = $1.size(); 

    npy_intp dims[1] = { result_size }; 

    PyArrayObject* npy_arr = (PyArrayObject*)PyArray_SimpleNew(1, dims, NPY_INT); 
    int* dat = (int*) PyArray_DATA(npy_arr); 

    for (size_t i = 0; i < result_size; ++i) { 
     dat[i] = $1[i]; 
    } 

    $result = PyArray_Return(npy_arr); 
} 

यह सी-स्तर numpy कार्यों का उपयोग करता का निर्माण और एक सरणी वापस जाने के लिए:

यहाँ कुछ कोड है जो NumPy पूर्णांक विन्यास में, सभी std::vector<int> वस्तुओं हो जाएगा है।आदेश में, यह:

  • यह सुनिश्चित करता है NumPy के arrayobject.h फ़ाइल सी ++ आउटपुट फ़ाइल में शामिल है जब पायथन मॉड्यूल लोड किया जाता है
  • कारणों import_array के नाम से जाना (अन्यथा, सभी NumPy तरीकों SEGFAULT जाएगा)
  • मैप्स किसी भी एक typemap

साथ NumPy सरणी में std::vector<int> के रिटर्न इस कोड को आप से पहले रखा जाना चाहिए %import हेडर क ich में std::vector<int> लौटने वाले फ़ंक्शन शामिल हैं। उस प्रतिबंध के अलावा, यह पूरी तरह आत्मनिर्भर है, इसलिए इसे आपके कोडबेस में बहुत अधिक व्यक्तिपरक "गड़बड़" नहीं जोड़ना चाहिए।

आप अन्य वेक्टर प्रकार की जरूरत है, तो आप सिर्फ NPY_INT और सभी int* और int बिट्स को बदल सकते हैं, नहीं तो ऊपर समारोह डुप्लिकेट।

+0

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

संबंधित मुद्दे

 संबंधित मुद्दे