2016-05-20 5 views
0

Ich habe ein Cython-Modul geschrieben, das eine fremde C-Funktion umschließt, und es funktioniert wie erwartet. Ich möchte jedoch die restlichen Funktionen meiner C-Binärdatei, die identische Signaturen haben, bereitstellen. In Python, konnte ich nur tun:Wie man ein Cython-Modul mit vielen identischen Funktionssignaturen strukturiert

def boilerplate(func): 
    def wrapped_f(c, d): 
     # modify x and y, producing mod_c and mod_d 
     result = func(mod_c, mod_d) 
     # modify foreign function return values, producing final_c, final_d 
     return final_c, final_d 
    return wrapped_f 

@boilerplate 
def func_a(a, b) 
    return _foreign_func_a(a, b) 

@boilerplate 
def func_b(a, b) 
    return _foreign_func_b(a, b) 

Gibt es ein ähnliches Muster, das ich in Cython, um verwenden kann, um "cythonise" wrapped_f, unter der Annahme, _foreign_func_a und der begleitende structs usw. hat cimport ed gewesen?

Allerdings, wenn ich bewegen, um die allgemeinen Vorgänge in den Dekorateur:

def boilerplate(func): 
    def wrapped(double[::1] wlon, double[::1] wlat): 
     cdef _FFIArray x_ffi, y_ffi 
     x_ffi.data = <void*>&wlon[0] 
     x_ffi.len = wlon.shape[0] 
     y_ffi.data = <void*>&wlat[0] 
     y_ffi.len = wlat.shape[0] 
     cdef _Result_Tuple result = func(x_ffi, y_ffi) 
     cdef double* eastings_ptr = <double*>(result.e.data) 
     cdef double* northings_ptr = <double*>(result.n.data) 
     cdef double[::1] e = <double[:result.e.len:1]>eastings_ptr 
     cdef double[::1] n = <double[:result.n.len:1]>northings_ptr 

     e_numpy = np.copy(e) 
     n_numpy = np.copy(n) 
     drop_float_array(result.e, result.n) 
     return e_numpy, n_numpy 
    return wrapped 

@boilerplate 
def convert_bng(double[::1] lons, double[::1] lats): 
    """wrapper around threaded conversion function 

    """ 
    return convert_to_bng_threaded(lons, lats) 

ich Fehler erhalten, wenn

  • versucht x_ffi und y_ffi-_FFIArray zu Python-Objekte zu konvertieren in wrapped
  • Umwandlung Python-Objekt func bis _Result_Tuple in wrapped
  • lons und lats-_FFI_Array in convert_to_bng_threaded Konvertieren und
  • _Result_Tuple zurück zu einem Python-Objekt in convert_bng_threaded
+0

Ich kann es falsch zu lesen, aber es sieht aus wie Sie gefragt werden könnten eines von zwei Dingen. 1) Wenn Sie vermeiden wollen, dass Sie schreiben müssen, kleine, einzeilige Wrapper-Funktionen für jede fremde Funktion zu schreiben, dann glaube ich nicht, dass Sie es können. 2) Wenn Sie Dekoratoren verwenden möchten, dann unterstützt Cython es und Sie können es wie geschrieben tun (obwohl es wahrscheinlich nicht kompilieren wird, um C-Code sehr sauber zu machen). – DavidW

+0

@DavidW ah, entschuldigung. Mir wäre es recht, eine Menge Wrapper-Funktionen zu schreiben, um ehrlich zu sein. Ich wusste nicht, dass ich solche Dekoratoren in Cython verwenden könnte. Ich gebe es eine Chance und profiliere das Ergebnis ... – urschrei

+0

@urschei Es unterstützt die große, große, überwiegende Mehrheit von Python-Code (so ist es immer wert, nur geben Sie Ihren Code los). Es gelingt ihm nicht immer, es in besonders schnellen C-Code zu übersetzen. – DavidW

Antwort

1

Ihr wesentliches Problem (basierend auf Ihre Frage aktualisiert) Umwandlung ist, dass Sie versuchen, eine wickeln Funktion, die reine C-Datentypen verwendet (und daher nur als cdef-Funktion definiert werden kann und von Cython, aber nicht von Python aufgerufen werden kann). Dekoratoren arbeiten jedoch an Python-Funktionen, so dass sie nicht zusammenkommen.

Glücklicherweise können Sie etwas sehr ähnliche Handhabung der verpackten Funktion a mit C-Funktionszeiger tun. Sie benötigen eine etwas andere Syntax, aber die Idee ist sehr ähnlich. (Aus Gründen der Antwort, die ich nehme an, dass Sie die Definitionen von C-Datentypen von this previous question verwenden, was meiner Meinung nach sinnvoll ist)

# pass a function pointer in 
cdef boilerplate(_Result_Tuple (*func)(_FFIArray, _FFIArray)): 
    def wrapped(double[::1] wlon, double[::1] wlat): 
     cdef _FFIArray x_ffi, y_ffi 
     x_ffi.data = <void*>&wlon[0] 
     x_ffi.len = wlon.shape[0] 
     y_ffi.data = <void*>&wlat[0] 
     y_ffi.len = wlat.shape[0] 
     cdef _Result_Tuple result = func(x_ffi, y_ffi) 
     cdef double* eastings_ptr = <double*>(result.e.data) 
     cdef double* northings_ptr = <double*>(result.n.data) 
     cdef double[::1] e = <double[:result.e.len:1]>eastings_ptr 
     cdef double[::1] n = <double[:result.n.len:1]>northings_ptr 

     e_numpy = np.copy(e) 
     n_numpy = np.copy(n) 
     drop_float_array(result.e, result.n) 
     return e_numpy, n_numpy 
    return wrapped 

# do this instead of using a decorator syntax 
convert_bng = boilerplate(&convert_to_bng_threaded) 
+0

Vielen Dank! Ihre zwei Antworten waren wertvoller als alle Dokumente oder Cython-Beispiele, die ich gelesen habe. – urschrei

Verwandte Themen