2010-10-13 14 views
5

समस्या: मैंने SWIG का उपयोग करके अजगर में कुछ सी ++ कोड लपेट लिया है। अजगर की तरफ, मैं एक लपेटा हुआ सी ++ पॉइंटर लेना चाहता हूं और इसे उप-वर्ग में पॉइंटर होने के लिए नीचे डालना चाहता हूं। मैंने SWIG .i फ़ाइल में एक नया सी ++ फ़ंक्शन जोड़ा है जो यह डाउन-कास्टिंग करता है, लेकिन जब मैं इसे पायथन से कॉल करता हूं, तो मुझे टाइप एरर मिलता है।मैं एक पाइथन SWIG wrapper से C++ ऑब्जेक्ट को डाउन-कैस्ट कैसे करूं?

मैं दो C++ कक्षाएं, बेस और व्युत्पन्न है:

यहाँ विवरण हैं। व्युत्पन्न बेस का उप-वर्ग है। मेरे पास एक तीसरी कक्षा है, कंटेनर, जिसमें एक व्युत्पन्न है, और इसमें एक एक्सेसर प्रदान करता है। एक्सेसर, दिखाया गया है एक स्थिरांक बेस & के रूप में व्युत्पन्न रिटर्न:

class Container { 
    public: 
    const Base& GetBase() const { 
     return derived_; 
    } 

    private: 
    Derived derived_; 
}; 

मैं बड़ा घूँट का उपयोग कर अजगर में इन कक्षाओं में लिपटे गए हैं। मेरे पायथन कोड में, मैं आधार संदर्भ को नीचे व्युत्पन्न करने के लिए नीचे कास्ट करना चाहता हूं। ऐसा करने के लिए, मैं बड़ा घूँट में लिखा है C++ जो नीचे कास्टिंग करता है में एक सहायक समारोह फाइल मैं:

base = container.GetBase() 
derived = CastToDerived(base) 
:

%inline %{ 
    Derived* CastToDerived(Base* base) { 
    return static_cast<Derived*>(base); 
    } 
%} 

मेरी अजगर कोड में, मैं यह नीचे कास्टिंग फ़ंक्शन को कॉल करें

जब मैं ऐसा है, तो मैं निम्नलिखित त्रुटि मिलती है:

TypeError: in method 'CastToDerived', argument 1 of type 'Base *' 

ऐसा क्यों हो रहा हो सकता है?

संदर्भ के लिए, यहां SWIG द्वारा जेनरेट की गई .cxx फ़ाइल के प्रासंगिक बिट्स हैं; अर्थात् मूल कार्य है, और उसके अजगर इंटरफ़ेस-वर्गीकृत कार्बन कॉपी:

Derived* CastToDerived(Base* base) { 
    return static_cast<Derived*>(base); 
    } 

// (lots of other generated code omitted) 

SWIGINTERN PyObject *_wrap_CastToDerived(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { 
    PyObject *resultobj = 0; 
    Base *arg1 = (Base *) 0 ; 
    void *argp1 = 0 ; 
    int res1 = 0 ; 
    PyObject * obj0 = 0 ; 
    Derived *result = 0 ; 

    if (!PyArg_ParseTuple(args,(char *)"O:CastToDerived",&obj0)) SWIG_fail; 
    res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_Base, 0 | 0); 
    if (!SWIG_IsOK(res1)) { 
    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "CastToDerived" "', argument " "1"" of type '" "Base *""'"); 
    } 
    arg1 = reinterpret_cast< Base * >(argp1); 
    result = (Derived *)CastToDerived(arg1); 
    resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_Derived, 0 | 0); 
    return resultobj; 
fail: 
    return NULL; 
} 

किसी भी मदद की बहुत सराहना की जाएगी।

- मैट

+0

क्या GetBase लिए बनाए गए कोड() कैसा दिखता है? त्रुटि का अर्थ है कि ऑस्ट ऑब्जेक्ट कोस्टोडेडिव में पास किया जा रहा है सही प्रकार नहीं है - यह किस प्रकार का है? –

+0

इसके लायक होने के लिए, मैंने स्विंग 1.3.40 का उपयोग करके उपरोक्त के आधार पर एक उदाहरण बनाने की कोशिश की, और मुझे यह त्रुटि नहीं मिली। –

+0

बहुत अजीब ... मैंने आपके उदाहरण, क्रिस की तरह कुछ लिखने की कोशिश की, और वास्तव में यह काम किया। जैसा कि आप उम्मीद कर सकते हैं, जिस कोड में मुझे वास्तव में परेशानी हो रही है वह खिलौना की समस्या नहीं है, मैं सिर्फ खिलौना-अगर इसे किसी प्रश्न में फिट करने के लिए पर्याप्त छोटा बनाता हूं। मेरा वर्तमान वर्कअराउंड मेरी C++ लाइब्रेरी में CastToDerived फ़ंक्शन को परिभाषित करना है, बजाय% inline% {...%} .i फ़ाइल में ब्लॉक करें। यह समस्या को हल करता है। शायद वह विवरण सही व्यक्ति के लिए संकेत हो सकता है? मुझे अभी भी इच्छा है कि मैं अपने सी ++ लाइब्रेरी में एसडब्ल्यूआईजी हेल्पर्स जोड़ने के बिना कर सकता हूं। – SuperElectric

उत्तर

3

जैसा कि मैंने ऊपर टिप्पणी की है, यह स्विंग 1.3.40 के साथ ठीक काम करता प्रतीत होता है।

c.h:

#include <iostream> 
class Base {}; 
class Derived : public Base 
{ 
    public: 
     void f() const { std::cout << "In Derived::f()" << std::endl; } 
}; 
class Container { 
    public: 
    const Base& GetBase() const { 
     return derived_; 
    } 
    private: 
    Derived derived_; 
}; 

c.i

%module c 

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

%inline %{ 
    Derived* CastToDerived(Base* base) { 
    return static_cast<Derived*>(base); 
    } 
%} 
class Base 
{ 
}; 

class Derived : public Base 
{ 
    public: 
     void f() const; 
}; 

class Container { 
    public: 
    const Base& GetBase() const; 
}; 

ctest

यहाँ मेरी फ़ाइलें हैं।py

import c 

container = c.Container() 
b = container.GetBase() 
d = c.CastToDerived(b) 
d.f() 
print "ok" 

एक रन:

$ swig -c++ -python c.i 
$ g++ -fPIC -I/usr/include/python2.6 -c -g c_wrap.cxx 
$ g++ -shared -o _c.so c_wrap.o 
$ python ctest.py 
In Derived::f() 
ok 
0

2 बातें मैं अपने कोड 1 GetBase में नोटिस const के लिए एक संदर्भ और दूसरी रिटर्न कि CastToDerived गैर स्थिरांक बेस के लिए सूचक की उम्मीद है।

यहां तक ​​कि सी ++ में आपको इस काम को करने में काफी परेशानी होगी। मैं यह नहीं बता सकता कि और क्या गलत होना चाहिए, लेकिन मैं इसे पहले fxied पाने की कोशिश करता हूं।

+0

यह समस्या नहीं है, मुझे लगता है। मूल CastToDerived ने एक कॉन्स्ट संदर्भ लिया, और एक कॉन्स पॉइंटर वापस कर दिया, जैसा कि आप सुझाव दे सकते हैं। तब भी मुझे वही त्रुटि थी। एसडब्ल्यूआईजी सभी संदर्भ लेता है और उन्हें पॉइंटर्स में बदल देता है, और स्थिरता छोड़ देता है। यही कारण है कि मेरा CastToDerived अब गैर-कॉन्स्ट पॉइंटर्स लेता है और देता है। पुन: यहां स्विग डॉक्स: http://www.swig.org/Doc2.0/SWIGPlus.html#SWIGPlus_nn18 और यहां: http://www.swig.org/Doc2.0/SWIGPlus.html#SWIGPlus_const – SuperElectric

0

क्या यह संभव है कि आप बेस क्लास को कई बार परिभाषित कर रहे हों? मुझे सीटीपीएस के साथ समान समस्याएं आई हैं जहां मैंने अनजाने में एक ही संरचना वर्ग को दो अलग-अलग मॉड्यूल में परिभाषित किया है। मेरे पास शुद्ध पायथन में कुछ ऐसा ही हुआ है, जहां मैंने प्लगइन क्लास लोड करने के लिए imp.load_module का उपयोग किया, उस वर्ग का ऑब्जेक्ट बनाया, फिर मॉड्यूल को पुनः लोड किया - पोफ! निर्मित ऑब्जेक्ट अब कक्षा के एक इंस्टीटेंस टेस्ट को पास नहीं करेगा, क्योंकि रीलोडेड क्लास, भले ही उसका नाम समान हो, अलग आईडी के साथ एक अलग वर्ग था। (this blog entry में अधिक पूर्ण विवरण।)

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