2012-12-21 9 views
12

Sto cercando di usare python (CPython) nel mio programma per consentire lo scripting dell'utente nel mio ambiente e per permettermi di usare pyside, i collegamenti qt per C++ per creare il GUI per la mia applicazione. Questi possono essere separati efficacemente con l'idea che il codice Python della GUI possa essere successivamente compilato per la velocità (se ciò sarebbe possibile).Genera collegamenti Python, quali metodi/programmi usare

Sono molto nuovo in Python e sto davvero cercando il modo più efficiente per generare binding solidi con il minimo assoluto di codice aggiuntivo da mantenere poiché è probabile che i binding cambino spesso mentre il progetto si evolve. Ne ho bisogno in modo che le classi python estendano le classi C++ che hanno virtuals.

Ho già esaminato PyBindGen e si soffoca troppo spesso su cose nella mia libreria perché sia ​​praticamente utile.

Qualsiasi aiuto/consiglio/link/flusso di lavoro che si consiglia a questo proposito sarebbe molto utile.

+0

IMHO le tue parti Python e C++ sono quindi inclini ad intrecciarsi tra di loro in ogni caso, se ci si integra a quel livello. Ma sostengo la ricerca di legami piacevoli in generale. +1. –

risposta

0

AFAICT, non ci sono molte opzioni con C++. Uno dei progetti precedenti è SWIG; si dice che sia un po 'arcano e goffo, ma dal momento che è in giro da molto tempo dovrebbe coprire anche molte cose non gestite da altri progetti. Potresti anche voler dare un'occhiata a Cython.

2

Se stai cercando la velocità, voterei sicuramente anche per Cython. Per quanto ne so su altri modi per interfacciare C++ con Python, Cython non è tanto pesante da mantenere/aggiornare rispetto ad altri strumenti di collegamento, per quanto riguarda il guadagno di "fluidità del flusso di lavoro". (Il codice Cythonized sostiene di essere veloce quanto la pura C, o non molto lontano da quello, che lo rende anche molto interessante).

In ogni caso, ci sono molte buone API per il collegamento del codice Python con C++ (Boost.Python, ...), ma penso che tutti loro porteranno all'esigenza di esporre i metodi direttamente nel codice sorgente C++ (Voi ragazzi dimmi se ho torto o impreciso).

D'altra parte, Cython ti darà la possibilità di mantenere la tua API C++ (GUI, o qualsiasi altra cosa ...) rigorosamente separata dalle fonti di esposizione (le cosiddette estensioni .pyx). Il flusso di lavoro finale sarebbe:

API C++ => Compilazione come oggetto condiviso => ​​estensione di Cython (importazione ed esposizione di caratteristiche C++) => Compilazione dell'estensione (s) => Uso dell'estensione (estensione da aggiunto al tuo percorso Python).

La buona notizia è che dovrete mantenere solo le parti mutevoli del vostro pool di file .pyx relativi alle funzionalità C++ in evoluzione (tra quelle che richiedono di essere esposte). All'inizio è una specie di investimento, ma, per esperienza, una volta che questo flusso di lavoro è stato impostato, è abbastanza semplice far crescere tutta la complessità.

Ora riguardo alla necessità di estendere le classi che hanno virtuals e di sovrascriverle da Python (se ho capito correttamente cosa intendevi). È fattibile Ancora una volta, non così diretto, ma dovresti dare un'occhiata a questo thread.

Le cattive notizie: in quel caso particolare dovrete creare degli adattatori/interfacce C++ extra, per abilitare la chiamata del metodo genitore se il python esteso non sovrascrive il metodo del genitore dato. (Si noti che la ridefinizione di un metodo esposto C++, virtuale o meno, da python è una sostituzione della funzione, ma non è assolutamente equivalente a una sostituzione).

Hummf, ora che mi sto leggendo, sembra un po 'confuso. Spero che questo sia ancora utile.

Posso essere più specifico sul flusso di lavoro che dovrai gestire se scegli l'opzione Cython, se me lo chiedi, ma penso che il thread collegato sopra sia piuttosto un buon punto di partenza ...

+0

Se hai bisogno di ulteriori dettagli sul wrapping della libreria C/C++ con Cython, potresti trovare utile anche un post che ho scritto a riguardo - ha tutti i dettagli necessari per avvolgere e distribuire una libreria C/C++: http: // martinsosic. com/development/2016/02/08/wrapping-c-library-as-python-module.html – Martinsos

11

Esistono solo due progetti con generatori di binding automatico per C++. Il primo è SWIG. Come alcune altre risposte hanno già detto, è un po 'vecchio stile, ma funziona. Il secondo è Boost.Python - da solo, non genera automaticamente i binding, ma puoi usare Boost.Pyste per farlo per te. Richiede GCC-XML per analizzare il codice sorgente originale e scrivere i binding Boost.Python. Entrambe le opzioni supportano metodi virtuali in C++ che possono essere sovraccaricati da Python.

Detto questo, devo completare il fatto che, normalmente, quando sei impegnativo, non leghi ciecamente tutto ciò che hai in C++ in Python - se lo fai in questo modo non otterrai una sensazione molto pitonica dal lato pitone. Invece, si progetta come si vorrebbe usare la libreria in Python, nel modo più plateale possibile, e poi si torna indietro e si vede come applicarla al codice C++ usando una delle possibili librerie di binding. Ad esempio, invece di trattare con std::vector, preferiresti che le tue chiamate di libreria gestiscano elenchi o iterabili di Python. Se la tua libreria C++ riceve un std::map, ti piacerebbe che sia gestito con i dizionari Python. Se si tratta di un array, forse un numpy.ndarray sarebbe più conveniente. E così via ...

Detto questo, è ancora possibile progettare le associazioni in modo che la manutenzione sia ridotta al minimo.

Ecco una lista di altri Python/C++ avvolgimento, nel caso in cui si decide di cercare in giro un po 'più:

  1. SWIG - come già sapete
  2. Boost.Python - questo è ciò che usiamo normalmente intorno qui - abbastanza ben strutturato
  3. Cython - sintassi molto ordinato vicino al Python - dicono di essere molto più veloce di Boost.Python
  4. SIP - non molto diffusa, ma è lì
  5. PyBindGen - sostiene di essere il più veloce
  6. ECS:Python - novità
  7. PyCXX - C++ servizi per rendere più facile scrivere estensioni Python
  8. pybind11 - sintassi simile a Boost.Python, implementazione compatta grazie a C + +11.
  9. CLIF - CLIF fornisce una base comune per la creazione di generatori di wrapper C++ per varie lingue.

Per completezza, è anche possibile caricare il codice C compilato direttamente in Python senza creare associazioni formali. È possibile farlo utilizzando FFI con uno di questi due moduli Python:

  1. ctypes - Questo nativo di Python e non richiede installazione modulo esterno.
  2. cffi - Questo è un nuovo pacchetto ispirato al design equivalente sul Lua JIT.
+1

Una nuova aggiunta a questo elenco è pybind11 (https://github.com/wjakob/pybind11, http: // pybind11 .readthedocs.org/it/ultima /). Disclaimer: io sono l'autore. –

+0

@WenzelJakob Penso che dovresti aggiungere una nuova risposta con quella informazione e includere la dichiarazione di non responsabilità nel corpo di quel post. –

+0

Andre, se desideri prendere in considerazione l'aggiunta delle informazioni suggerite da Wenzel Jakob, fallo (Revisione 4 di questa risposta). –

0

Per moderna C++ utilizzare CLIF (https://github.com/google/clif). Non scopre la tua API, devi descriverla in termini Python.

CLIF ricompilerà la tua intestazione con l'ultimo compilatore LLVM/Clang e produrrà il codice sorgente C++ per un modulo di estensione Python.

Può comprendere strutture dati complesse: def f() -> dict<str, set<int>>.

0

Per moderna C++, l'uso cppyy: http://cppyy.readthedocs.io/en/latest/

Si basa su Cling, l'interprete C++ per Clang/LLVM. I binding sono in fase di esecuzione e non è necessaria alcuna lingua intermedia aggiuntiva. Grazie a Clang, supporta C++ 17.

Specifico per la domanda iniziale sull'utilizzo di Qt: diversi aggiornamenti recenti sono stati fatti esplicitamente per supportare la generazione dei bind per tutti i KDE.

Per velocità: cppyy è supportato nativamente da PyPy.

Nota: sono l'autore principale di cppyy.

Problemi correlati