2013-04-28 6 views
9

मुझे अच्छी तरह पता है कि वहाँ ग के लिए ++ कोई मानक ABI हूँ, इसलिए यह मैं क्या किया है:अजगर, सी बनाने के लिए ctypes का उपयोग कर ++ वर्ग आवरण

//trialDLL.h 
#ifndef TRIALDLL_H_ 
#define TRIALDLL_H_ 

class MyMathFuncs 
{ 
private: 
    double offset; 

public: 
    MyMathFuncs(double offset); 

    ~MyMathFuncs(); 

    double Add(double a, double b); 

    double Multiply(double a, double b); 

    double getOffset(); 
}; 

#ifdef __cplusplus 
extern "C"{ 
#endif 

#ifdef TRIALDLL_EXPORT 
#define TRIALDLL_API __declspec(dllexport) 
#else 
#define TRIALDLL_API __declspec(dllimport) 
#endif 

    TRIALDLL_API MyMathFuncs* __stdcall new_MyMathFuncs(double offset); 

    TRIALDLL_API void __stdcall del_MyMathFuncs(MyMathFuncs *myMath); 

    TRIALDLL_API double __stdcall MyAdd(MyMathFuncs* myMath, double a, double b); 


#ifdef __cplusplus 
} 
#endif 

#endif 

और परिभाषा सीपीपी: (अन्य दर्जे के प्रकार्य 'परिभाषाएं छोड़ी गई हैं)

//trialDLL.cpp 
#include "trialDLL.h" 

MyMathFuncs* __stdcall new_MyMathFuncs(double offset) 
{ 
return new MyMathFuncs(offset); 
} 


void __stdcall del_MyMathFuncs(MyMathFuncs *myMath) 
{ 
    myMath->~MyMathFuncs(); 
} 


double __stdcall MyAdd(MyMathFuncs *myMath, double a, double b) 
{ 
return myMath->Add(a, b); 
} 

// class functions 
double MyMathFuncs::Add(double a, double b) 
{ 
return a+b+ this->offset; 
} 

और मैं इसे एक डीएल में बना देता हूं और इसे परीक्षण डीएलएल 3 डीएल नाम देता हूं। फिर पायथन में, मैंने एक मॉड्यूल लिखा:

#trialDLL3.py 
import ctypes 
from ctypes import WinDLL 

class MyMath(object): 
    def __init__(self, offset): 
     self.FunMath = WinDLL('trialDLL3.dll') 
     self.FunMath.new_MyMathFuncs.argtypes = [ctypes.c_double] 
     self.FunMath.new_MyMathFuncs.restype = ctypes.c_void_p 

     self.FunMath.MyAdd.argtypes = [ctypes.c_void_p, \ 
             ctypes.c_double, ctypes.c_double] 
     self.FunMath.MyAdd.restype = ctypes.c_double 

     self.obj = self.FunMath.new_MyMathFuncs(offset) 

    def FunAdd(self, a, b): 
     self.FunMath.MyAdd(self.obj, a, b) 

    def delete(): 
     self.FunMath.del_MyMathFuncs() 

इन सभी के बाद, अजीब चीजें हुईं। आईडीएलई पायथन खोल में, मैंने किया:

theMath = MyMath(3.3)  #create the instance 
theMath.FunAdd(3.3, 3.3)  #call the function 

दूसरी पंक्ति 9.9 के बजाय कोई नहीं लौटा। तब मैं एक और तरीका दौर की कोशिश की, खोल में इस लाइन डालने:

theMath.FunMath.MyAdd(theMath.obj, 3.3 ,3.3) 

और इस लाइन मुझे एक unsurprising 9.9 है, लेकिन आश्चर्य की बात लौटाता है जब अंतिम परिणाम नहीं की तुलना में। इन दो लाइनों को समान नहीं होना चाहिए? (आयात को छोड़कर)

loadedDLL = WinDLL('trialDLL3.dll') 
loadedDLL.new_MyMathFuncs.argtypes = [ctypes.c_double] 
loadedDLL.new_MyMathFuncs.restype = ctypes.c_void_p 
loadedDLL.MyAdd.argtypes = [ctypes.c_void_p, \ 
            ctypes.c_double, ctypes.c_double] 
loadedDLL.MyAdd.restype = ctypes.c_double 
obj = loadedDLL.new_MyMathFuncs(3.3) 
FunMath.MyAdd(obj, 3.3, 3.3) 

इन सभी लाइनों अंत में 9.9 लौटे: और मैं अजगर खोल में स्पष्ट रूप से उन सभी लाइनों को चलाने और देखो क्या गलत, लेखन जा सकते हैं का फैसला किया। यदि परीक्षण DLL3.py मॉड्यूल आयात किया गया है तो क्या ये पंक्तियां दो पंक्तियों के समान नहीं हैं?

theMath = MyMath(3.3)  #create the instance 
theMath.FunAdd(3.3, 3.3)  #call the function 

यदि वे एक ही सौदे हैं, तो दो पंक्ति वर्ग संस्करण कोई नहीं लौटाता है और स्पष्ट तरीका वापसी 9.9 क्यों होती है? अग्रिम में धन्यवाद!

+0

धन्यवाद eryksun;) लेकिन मुझे लगता है कि बैकस्लैश हमेशा एक लाइन निरंतरता के लिए रखा जाता है, तो मुझे पठनीयता में सुधार होता है? – springRoll

उत्तर

5

सबकुछ ठीक काम करता है ... लेकिन आप MyMath विधि में सी फ़ंक्शन के रिटर्न वैल्यू के साथ पास करना भूल गए हैं। FunAdd!

def FunAdd(self, a, b): 
    return self.FunMath.MyAdd(self.obj, a, b) 
    ^^^^^^ 
+2

मेरा मेरा .. धन्यवाद Armin! रविवार की रात में काम करना अच्छा नहीं है, है ना? – springRoll

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