2010-05-07 10 views
6

Ho scritto un codice di simulazione fisica in C++ e l'analisi dei file di testo di input ne è un collo di bottiglia. Come uno dei parametri di input, l'utente deve specificare una funzione matematica che verrà valutata molte volte in fase di esecuzione. Il codice C++ ha alcune classi di funzioni predefinite per questo (in realtà sono piuttosto complesse sul lato matematico) e alcune capacità di analisi limitate, ma non sono affatto soddisfatto di questa costruzione.Passando l'oggetto C++ al codice C++ tramite Python?

Quello che mi serve è che sia l'algoritmo che la valutazione della funzione rimangano veloci, quindi è vantaggioso mantenerli entrambi come codice compilato (e preferibilmente, le funzioni matematiche come oggetti funzione C++). Tuttavia ho pensato di incollare l'intera simulazione insieme a Python: l'utente poteva specificare i parametri di input in uno script Python, mentre implementava anche lo storage, la visualizzazione dei risultati (matplotlib) e la GUI, anche in Python.

So che la maggior parte delle volte, esporre le classi C++ può essere fatto, ad es. con SWIG ma ho ancora una domanda riguardante l'analisi della funzione matematica definita dall'utente in Python:

È possibile in qualche modo costruire un oggetto funzione C++ in Python e passarlo all'algoritmo C++? E.g. quando chiamo

f = WrappedCPPGaussianFunctionClass(sigma=0.5) 
WrappedCPPAlgorithm(f) 

in Python, sarebbe restituire un puntatore ad un oggetto C++ che sarebbe poi passato a un C++ di routine che richiedono un tale puntatore, o qualcosa di simile ... (non mi chiedere di memoria gestione in questo caso, però: S)

il punto è che non callback occorre a Python codice nell'algoritmo. In seguito vorrei estendere questo esempio per fare anche un po 'di parsing di espressioni semplici sul lato Python, come somma o prodotto di funzioni, e restituire un composto, parse-tree come l'oggetto C++ ma per ora rimango ai concetti di base.

Ci scusiamo per il post lungo e per i suggerimenti in anticipo.

risposta

3

Faccio cose simili a questo tutto il tempo. La soluzione più semplice, e quella che scelgo di solito perché, se non altro, sono pigro, è di appiattire la tua API a un'API C-like e quindi passare solo i puntatori ae da Python (o l'altra lingua che preferisci).

Innanzitutto creare le vostre classi

class MyFunctionClass 
{ 
    public: 
    MyFunctionClass(int Param) 
    ... 
}; 

class MyAlgorithmClass 
{ 
    public: 
    MyAlgorithmClass(myfunctionclass& Func) 
    ... 
}; 

quindi creare un'API C-stile di funzioni che crea e distrugge quelle classi. Di solito mi sono accontentato di passare il vuoto * perché le lingue che uso non mantengono comunque la sicurezza del tipo. È solo più facile in questo modo. Basta fare in modo di gettare di nuovo al tipo giusto prima che realmente utilizzare il void *

void* CreateFunction(int Param) 
    { 
     return new MyFunctionClass(Param); 
    } 

    void DeleteFunction(void* pFunc) 
    { 
     if (pFunc) 
      delete (MyFunctionClass*)pFunc; 
    } 

    void* CreateAlgorithm(void* pFunc) 
    { 
     return new MyAlgorithmClass(*(MyFunctionClass*)pFunc) 
    } 

    void DelteAlgorithm(void* pAlg) 
    { 
     if (pAlg) 
      delete (MyAlgorithmClass*)pAlg; 
    } 

Non tutto quello che dovete fare è fare pitone chiamata di coloro che la funzione C-style. In effetti, possono (e probabilmente dovrebbero) essere le funzioni "c" esterne per rendere il collegamento molto più semplice.