2012-08-17 11 views
7

मैं कुछ दिनों के लिए पाइथन सूची में संरचनाओं की सरणी को कैसे चालू करना है, यह जानने का प्रयास कर रहा हूं। मेरे पास एक ऐसा फ़ंक्शन है जो सरणी की शुरुआत में पॉइंटर देता है।एसडब्ल्यूआईजी पायथन संरचना ऐरे

struct foo { 
    int member; 
}; 

struct foo *bar() { 
    struct foo *t = malloc(sizeof(struct foo) * 4); 
    ... do stuff with the structs ... 
    return t; 
} 

अजगर से समारोह मैं एक संरचना मिल बुला लेकिन सरणी के अन्य तत्वों का उपयोग करने की कोशिश के बाद एक त्रुटि का कारण बनता है:

foo = bar() 
print foo[1].member 
TypeError: 'foo' object does not support indexing 

मैं %array_class उपयोग करने की कोशिश की है, लेकिन कोई लाभ नहीं हुआ। मैं भी बड़ा घूँट इंटरफ़ेस फ़ाइल में एक सरणी लौटने के रूप में समारोह को परिभाषित करने की कोशिश की है:

extern struct foo [ANY] bar(); 

बड़ा घूँट प्रलेखन सुंदर पूरी तरह से है, लेकिन मैं यह पता लगाने की नहीं कर पा रहे।

+1

क्या आपने यहां देखा है? - http://stackoverflow.com/questions/8114030/swig-python-array-inside- संरचना – dpandiar

+0

@dpandiar - यह एक अलग मामला है क्योंकि आकार निश्चित और ज्ञात है और सरणी सदस्य हैं और फ़ंक्शन से मान वापस नहीं करते हैं – Flexo

उत्तर

8

विचार जो आपने [ANY] के साथ प्रयास किया है, कई कारणों से काम नहीं करेगा। मुख्य रूप से ANY का उपयोग टाइपमैप में किया जा सकता है ताकि एक ही टाइपमैप को अलग-अलग आकार के सरणी के साथ काम करने की अनुमति मिल सके, जो कि आपके पास नहीं है।

सी के लिए सिंटैक्स या तो वहां क्वियर नहीं है। आप नहीं लिख सकते हैं:

int[4] bar() { 
    static int data[4]; 
    return data; 
} 

या:

int bar()[4] { 
    static int data[4]; 
    return data; 
} 

मानक निकटतम आप प्राप्त कर सकते हैं सी में है:

int (*bar())[4] { 
    static int data[4] = {1,2,3,4}; 
    return &data; 
} 

लेकिन वह वास्तव में किसी भी रैप करने के लिए आसान नहीं है। द्वारा

Python 3.2.3 (default, May 3 2012, 15:54:42) 
[GCC 4.6.3] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import test 
>>> arr = test.fooArray.frompointer(test.bar()) 
>>> arr 
<test.fooArray; proxy of <Swig Object of type 'fooArray *' at 0xb6f332a8> > 
>>> arr[0] 
<test.foo; proxy of <Swig Object of type 'struct foo *' at 0xb6f33038> > 
>>> arr[1] 
<test.foo; proxy of <Swig Object of type 'struct foo *' at 0xb6f33380> > 
>>> arr[2] 
<test.foo; proxy of <Swig Object of type 'struct foo *' at 0xb6f33398> > 
>>> arr[3] 
<test.foo; proxy of <Swig Object of type 'struct foo *' at 0xb6f330c8> > 
>>> 

हम एक कदम बेहतर हालांकि (संभवतः) जा सकते हैं:

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

%module test 

%inline %{ 
    struct foo { 
    int member; 
    }; 

    struct foo *bar() { 
    struct foo *arr = malloc(sizeof(struct foo) * 4); 
    for (int i = 0; i < 4; ++i) 
     arr[i].member = i; 
    return arr; 
    } 
%} 

%include <carrays.i> 
%array_class(struct foo, fooArray); 

यह सुविधा देता है मुझे करना bar() से पहले निम्नलिखित जोड़कर पॉइंटर को सरणी प्रकार में जोड़ने के लिए कोड को इंजेक्शन करना SWIG:

%pythonappend bar() %{ 
    # Wrap it automatically 
    val = fooArray.frompointer(val) 
%} 

तो अब यह पसंद का उपयोग कर सकते हैं:

Python 3.2.3 (default, May 3 2012, 15:54:42) 
[GCC 4.6.3] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import test 
>>> test.bar()[1].member 
1 
>>> arr = test.bar() 
>>> arr[3].member 
3 

आप स्मृति स्वामित्व के बारे में सावधान रहने की जरूरत है। इन उदाहरणों में अब तक स्मृति लीक हो गई है। एसडब्ल्यूआईजी को यह बताने के लिए आप %newobject का उपयोग कर सकते हैं कि मेमोरी पाइथन पक्ष के स्वामित्व में है, लेकिन फिर इसे बहुत जल्दी रिलीज़ किया जाएगा (जैसे ही मूल वापसी मूल्य अब संदर्भित नहीं किया जाता है) तो आपको मूल मूल्य को चारों ओर रखने की व्यवस्था करनी होगी लंबे समय तक। कि की एक पूरी उदाहरण है, जो रूप में लंबे समय सरणी आवरण के रूप में चारों ओर एक संदर्भ रखने के लिए सरणी वर्ग के उदाहरण के अंदर मूल सूचक बचाता ही होगा:

%module test 

%pythonappend bar() %{ 
    # Wrap it automatically 
    newval = fooArray.frompointer(val) 
    newval.ptr_retain = val 
    val = newval 
%} 

%newobject bar(); 

%inline %{ 
    struct foo { 
    int member; 
    }; 

    struct foo *bar() { 
    struct foo *arr = malloc(sizeof(struct foo) * 4); 
    for (int i = 0; i < 4; ++i) 
     arr[i].member = i; 
    return arr; 
    } 
%} 

%include <carrays.i> 
%array_class(struct foo, fooArray); 

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

+0

आपको बहुत बहुत धन्यवाद! यह वही है जो मैं खोज रहा था और पूरी तरह से काम किया था। मुझे एक गणना से सरणी का आकार पता है जिसे मैंने उदाहरण को सरल बनाने के लिए शामिल नहीं किया था। मैंने पहले carrays.i पर प्रलेखन देखा था, लेकिन मैं इससे उलझन में था: "इस मैक्रो का उपयोग करते समय, प्रकार को सरल प्रकार के नाम जैसे int, float, या Foo तक सीमित किया जाता है।" मैं 'struct foo *' प्रकार का उपयोग करने की कोशिश करता रहा और जब यह काम नहीं किया गया तो यह माना जाता है कि यह केवल मूल सी प्रकारों के लिए काम करेगा। – user1604630

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