2015-07-15 14 views
10

Domanda

C'è un modo per creare un wrapper Python per la classe C++ con wrapper Cython con i modelli? (Esegui esattamente ciò che è mostrato qui ma con i modelli: http://docs.cython.org/src/userguide/wrapping_CPlusPlus.html#create-cython-wrapper-class).Cython: modelli in wrapper di classe python

Sono a conoscenza dei tipi di fusibile soluzione (https://groups.google.com/forum/#!topic/cython-users/qQpMo3hGQqI) ma ciò non consente di instaziare classi come vector<vector<int>>: i tipi con fusione hanno, non sorprendentemente, nessuna nozione di ricorsione.

Riformulare

Quello che vorrei realizzare è per una classe avvolto come:

cdef extern from "header.h": 
    cdef cppclass Foo[T]: 
     Foo(T param) 
     # ... 

creare un semplice involucro Python:

cdef class PyFoo[T]: # I know the '[T]' can't be here, it's a wish 
    cdef Foo[T] *thisptr 
    def __cinit__(self, param): 
     self.thisptr = new Foo[T](param) 
    # ... 

Sono abbastanza sicuro che doesn Cython supportarlo di per sé, ma forse qualcuno può pensare a una soluzione alternativa. Non sto cercando esempi idiomatici o simpatici, mi sto solo chiedendo se è possibile in qualsiasi modo.

+1

Che ne dici di eseguirlo attraverso una sorta di sostituzione di stringhe per generare un file sorgente diverso per ogni 'T'? – DavidW

+0

Quindi, in sostanza, cosa fa il compilatore C++ per i template, ma per i wrapper Cython? Ci ho pensato. È sicuramente un'opzione che sto considerando, anche se in qualche modo sta estendendo il compilatore cython e un bel po 'di lavoro. – piotrMocz

+0

Penso che intendessi qualcosa di molto più semplice: 1) crea un file contenente 'cdef class PyFoo_ {T}: cdef Foo [{T}] * thisptr' ecc. 2) Genera un mucchio di file cython facendo' .format (T = 'std :: vector ') ', e salvando i risultati. 3) Includere questi file nel file Cython principale (synatax 'include" nomefile.pxi "'). Ovviamente devi scegliere le classi da generare manualmente, ma devi sempre farlo. – DavidW

risposta

7

Come dici tu, Cython in realtà non supporta questo.

Penso che l'approccio più semplice sia semplicemente quello di generare manualmente un gruppo di file Cython utilizzando la sostituzione di stringhe. Inizia con un file "foowrapper.pxi.src" (nome che si desidera ...):

cdef class PyFoo_{T}: 
    cdef Foo[{T}] *thisptr 
    def __cinit__(self, param): 
    self.thisptr = new Foo[{T}](param) 
    # etc 

Avanti, gestito attraverso un semplice programma (può anche essere Python) per caricare il file, fare il sostituzione delle stringhe e salvare di nuovo il file con un nuovo nome. La linea di chiave è solo:

output = code.format(T=T) # where T is a string with a C++ class name 
       # e.g. "int" or "std::vector<double>" 

(C'è ovviamente un po 'di codice relativo al caricamento e il salvataggio che ho saltato per pigrizia)

Poi, nel vostro Cython si file solo "include" la file generati per ogni classe. Il "include" il comando in Cython è un testo letterale comprendono (come il preprocessore C) e si aspetta un file .pxi:

cdef extern from "header.h": 
    cdef cppclass Foo[T]: 
     Foo(T param) 
     # ... 

include "foowrapper_int.pxi" 
include "foowrapper_vectordouble.pxi 
# etc 

Devi scegliere le classi di generare in fase di compilazione, ma questo è inevitabile (modelli sono una funzionalità in fase di compilazione), quindi non sarai mai in grado di generarli dinamicamente da un ambiente di scripting Python poiché la corrispondente classe C++ non verrà generata.

Altre opzioni

Un paio di altre opzioni valgono breve considerazione. Innanzitutto, è possibile ereditare Foo<T> da una classe base (ad esempio FooBase) che non dipende dal parametro del modello. Dovresti quindi eseguire il wrapping di FooBase in Cython (generando funzioni simili al costruttore per i casi che ti interessano). Questo è realmente fattibile solo se le funzioni che vuoi chiamare non hanno argomenti che dipendono dal tipo di template. Ovviamente questo comporta anche la modifica del codice C++.

L'opzione di sezione è di esaminare un diverso modo di eseguire il wrapping. Boost Python supporterà sicuramente questo in modo nativo (ma ha i suoi stessi svantaggi). Immagino che SIP/SWIG faccia anche fronte (ma non lo so).Si può tranquillamente mescolare e abbinare questi con Cython se necessario (importando il modulo generato contenente le classi del modello).

+0

Mi sembra di aver perso Boost Python nella mia ricerca, ho bisogno di dare un'occhiata più da vicino. Inoltre: ottima risposta, chiarisce davvero molte cose, grazie. – piotrMocz

Problemi correlati