2013-04-28 9 views
9

Sono ben consapevole che non c'è ABI standard per C++, quindi questo è quello che ho fatto:Python, utilizzando ctypes per creare C++ classe wrapper

//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 

E la cpp definizione: (Altre funzioni di classe 'definizioni sono omessi)

//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; 
} 

e io costruire questo in una DLL e chiamarono trialDLL3.dll. Poi in python, ho scritto un modulo come:

#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() 

Dopo tutti questi, cose strane accadute. Nella shell Python IDLE, ho fatto:

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

La seconda linea restituito Nessuno invece di 9,9. Poi ho provato un altro modo rotondo, mettendo questa linea nella shell:

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

E questa linea mi restituisce un sorprendente 9,9, ma sorprendente se rispetto all'ultimo risultato Nessuno. Non dovrebbero queste due linee identiche? E ho deciso di correre tutte quelle linee in modo esplicito in guscio di pitone e vedere che cosa può andare storto, la scrittura: (escludendo le importazioni)

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) 

Tutte queste linee finalmente tornato 9.9. Non sono queste linee identiche alle due linee se il modulo trialDLL3.py è importato?

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

Se sono lo stesso affare, perché la versione della classe due linee restituisce None e il modo esplicito rendimento atteso 9.9? Grazie in anticipo!

+0

Grazie eryksun;) Ma penso che migliori la leggibilità se il backslash è sempre posizionato per una continuazione di riga? – springRoll

risposta

5

Tutto funziona correttamente ... ma si è dimenticato di passare il valore restituito della funzione C nel metodo MyMath.FunAdd!

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

My my .. Grazie Armin! Non è una buona idea lavorare alla domenica sera, vero? – springRoll

Problemi correlati