2015-04-28 4 views
6

के माध्यम से C++ करने के लिए अजगर उदाहरण पारित करने के लिए मैं बड़ा घूँट 2.0 के साथ इंटरफेस लपेटकर द्वारा पायथन (2.7) के साथ मेरी लाइब्रेरी का विस्तार कर रहा हूँ, और एक ग्राफ वस्तु जिसमें मैं एक आगंतुक बनाने के लिए चाहते हैं। सी ++, इंटरफ़ेस इस तरह दिखता है:कैसे अजगर/सी एपीआई

struct Visitor 
    { 
     virtual void OnStateBegin() = 0; 
     virtual void OnNode(Node* n) = 0; 
     virtual void OnStateEnd() = 0; 
    }; 

मैं पायथन में एक वर्ग है कि बराबर, अजगर के सारे परिभाषित करता है, जो किसी विज़िटर की परिभाषा के लिए अनुमति देगा परिभाषित करना चाहते हैं:

class GraphVisitor: 
    def __init__(self, label): 
     self._label = label 
     print("__init__(self,{0})".format(self._label)) 
    def OnStateBegin(self): 
     print("OnStateBegin()" + self._label) 
    def OnNode(self, i_node): 
     print("OnNode()" + self._label) 
    def OnStateEnd(self): 
     print("OnStateEnd()" + self._label) 

और जो मैं करने की कोशिश कर रहा हूं वह पाइथन लिपि में ग्राफ़विजिटर का एक उदाहरण बना रहा है, और C++ से दिए गए उदाहरण के लिए OnStateBegin(), OnNode(), और OnStateEnd() विधियों को कॉल करें। यहाँ मैं अजगर में क्या करना चाहते हैं क्या करना है:

#model is a SWIG wrapped class 
mvis = GraphVisitor("This is a test") 
model.Visit("mvis") # I'm not sure how to pass the instance 'mvis' to C++? 

और मेरी सी ++ बड़ा घूँट से लिपटे में, मुझे यकीन है कि कैसे उदाहरण 'mvis' पर प्राप्त करने के लिए नहीं कर रहा हूँ? मैं पाइथन में परिभाषित कार्यों को कॉल कर सकता हूं कोई समस्या नहीं, लेकिन उदाहरणों ने मुझे स्टंप कर दिया है!

+1

'mvis' सिर्फ एक अजगर वर्ग का एक उदाहरण है। यह आपके 'संरचना आगंतुक' के साथ नहीं कर रहा है। सी/सी ++ में आप इसे केवल 'पायओब्जेक्ट *' के रूप में एक्सेस कर सकते हैं। – Thomas

+0

मुझे पता है कि। मैं यह वर्णन करने की कोशिश कर रहा था कि मैं अजगर में एक आगंतुक को परिभाषित करने की कोशिश कर रहा हूं और सी ++ समकक्ष है। –

+1

क्या आपने मेरा पिछला उत्तर देखा है: http://stackoverflow.com/questions/9040669/how-can-i-implement-ac-class-in-python-to-be-called-by-c/9042139#9042139 (आप एम्बेडिंग के बारे में बिट्स को छोड़ सकते हैं, लेकिन एक पीओओब्जेक्ट से सी ++ इंटरफेस में कनवर्ट करने के बारे में थोड़ा वही है जो आप चाहते हैं) – Flexo

उत्तर

0

मुझे नहीं पता कि एसडब्ल्यूआईजी के साथ यह संभव है, लेकिन आप इसे SIP के साथ कर सकते हैं।

sip_vector_test.h:

class EXPORT Node { 
public: 
    explicit Node(int n) : n_(n) {}; 
    int getN() const { return n_; } 
private: 
    int n_; 
}; 
struct EXPORT NodeVisitor { 
    virtual void OnNode(Node* n) = 0; 
}; 
struct EXPORT Graph { 
public: 
    void addNode(int num); 
    void accept(NodeVisitor *nv); 
private: 
    std::vector< std::shared_ptr<Node> > nodes_; 
}; 

visitor.sip:

%Module pyvisit 

%ModuleHeaderCode 
#include "sip_visitor_test.h" 
%End 

class Node { 
public: 
    explicit Node(int n); 
    int getN() const; 
}; 
struct NodeVisitor { 
    virtual void OnNode(Node* n) = 0; 
}; 
struct Graph { 
public: 
    void addNode(int num); 
    void accept(NodeVisitor *nv); 
}; 

अजगर से उपयोग करना:

>>> import pyvisit 
>>> g = pyvisit.Graph() 
>>> g.addNode(3) 
>>> g.addNode(5) 
>>> class PyNodeVisitor(pyvisit.NodeVisitor): 
>>>  def OnNode(self, node): 
>>>   print(node.getN()) 
>>> pnv = PyNodeVisitor() 
>>> g.accept(pnv) 
3 
5 

मैं एक zip file रख दिया है इस के स्रोत कोड युक्त मेरे होमपेज पर परीक्षण परियोजना।

+0

उत्तर के लिए बहुत बहुत धन्यवाद! मैं एसआईपी का उपयोग नहीं कर रहा हूं, और यह देखना चाहता था कि यह नया प्रकार जोड़ने के बिना किया जा सकता है या नहीं। –

1

इस समस्या को हल करने के लिए, मैं मॉड्यूल से वर्ग को देखते हुए लिया गया यह मॉड्यूल का नाम और वर्ग के नाम (कोड के नीचे मान लिया मॉड्यूल पहले से ही लोड नहीं की गई):

void Model::Visit(const char* mod_name, const char* class_name) 
{ 
    PyErr_Clear(); 
    PyObject* mod_name_obj = PyString_FromString(mod_name); 
    PyObject* class_name_obj = PyString_FromString(class_name); 

    PyObject* py_module = PyImport_Import(mod_name_obj); 
    PyObject* err_1 = PyErr_Occurred(); 
    if(err_1) 
     PyErr_Print(); 

एक बार मैं था मॉड्यूल, मैं कक्षा ऊपर देखा यह शब्दकोश है से:

if(py_module) 
    { 
     PyObject* py_module_dict = PyModule_GetDict(py_module); 
     PyObject* py_class = PyDict_GetItem(py_module_dict, class_name_obj); 

मैं सी ++ में अजगर वर्ग instantiating द्वारा एक सा मेरी समस्या को सरल बनाया है, तो अपने आगंतुक बनाया, और अंत में यह देखा गया:

 if(py_class && PyClass_Check(py_class) && PyCallable_Check(py_class)) 
     { 
      PyObject* inst = PyInstance_New(py_class, 0, 0); 

      if(inst && PyInstance_Check(inst)) 
      { 
       IModel::IVisitorPtr py_visitor = new PyModelVisitor(inst); 

       _model->Visit(py_visitor); 
      } 
     } 
    } 
} 

आगंतुक था 3 कार्यों OnStateBegin(), OnNode(), और OnStateEnd()। मैंने अपने एसडब्ल्यूआईजी पायथन बाध्यकारी जनरेटर को -external-runtime option के साथ एसडब्ल्यूआईजी रनटाइम के बाहरी उपयोग के लिए हेडर फ़ाइल जेनरेट करने का विकल्प जोड़ा, इसलिए मैं सी ++ (नीचे INode *) में एक कक्षा बना सकता हूं और इसे पायथन पर तर्क के रूप में पाइथन में भेज सकता हूं ऑननोड() सदस्य फ़ंक्शन निम्नानुसार है (ब्रेवटी के लिए त्रुटि जांच हटा दी गई है):

VisitorCtrl OnNode(INode* node) 
{ 
    Node* node_impl = new NodeImpl(node); 
    PyObject* pynode = SWIG_NewPointerObj(node_impl, SWIG_TypeQuery("Node *"), 0); 
    PyObject* result = PyObject_CallMethodObjArgs(_inst, PyString_FromString("OnNode"), pynode, 0); 

    long rivis = PyInt_AsLong(result); 

    return(static_cast<VisitorCtrl>(rivis)); 
}