2017-10-07 5 views
2

J'ai une fonction C++ basée sur un modèle dont j'aimerais pouvoir utiliser les deux types. Comme Python ne supporte pas la surcharge, je suis un peu coincé pour résoudre ce problème. J'ai un .pyx comme indiqué ci-dessous. Comment puis-je utiliser la fonction C++ à la fois dans float et double?Comment utiliser une fonction de modèle en C++ pour deux types en Cython?

import cython 
import numpy as np 
cimport numpy as np 

# declare the interface to the C code 
cdef extern from "diff_cpp.cpp" namespace "diff": 
    cdef void diff_cpp[float] (float* at, const float* a, const float visc, 
           const float dxidxi, const float dyidyi, const float dzidzi, 
           const int itot, const int jtot, const int ktot) 

cdef extern from "diff_cpp.cpp" namespace "diff": 
    cdef void diff_cpp[double] (double* at, const double* a, const double visc, 
           const double dxidxi, const double dyidyi, const double dzidzi, 
           const int itot, const int jtot, const int ktot) 

@cython.boundscheck(False) 
@cython.wraparound(False) 
def diff(np.ndarray[double, ndim=3, mode="c"] at not None, 
     np.ndarray[double, ndim=3, mode="c"] a not None, 
     double visc, double dxidxi, double dyidyi, double dzidzi): 
    cdef int ktot, jtot, itot 
    ktot, jtot, itot = at.shape[0], at.shape[1], at.shape[2] 
    diff_cpp[double](&at[0,0,0], &a[0,0,0], visc, dxidxi, dyidyi, dzidzi, itot, jtot, ktot) 
    return None 

@cython.boundscheck(False) 
@cython.wraparound(False) 
def diff_f(np.ndarray[float, ndim=3, mode="c"] at not None, 
      np.ndarray[float, ndim=3, mode="c"] a not None, 
      float visc, float dxidxi, float dyidyi, float dzidzi): 
    cdef int ktot, jtot, itot 
    ktot, jtot, itot = at.shape[0], at.shape[1], at.shape[2] 
    diff_cpp[float](&at[0,0,0], &a[0,0,0], visc, dxidxi, dyidyi, dzidzi, itot, jtot, ktot) 
    return None 

MISE A JOUR AVEC LA SOLUTION

La réponse de @ OE1 fourni la bonne façon de le faire. C'est le code qui fonctionne, pour ceux qui sont intéressés par la solution à ce problème particulier.

import cython 
import numpy as np 
cimport numpy as np 

# declare the interface to the C code 
cdef extern from "diff_cpp.cpp" namespace "diff": 
    cdef void diff_cpp[T](T* at, const T* a, const T visc, 
          const T dxidxi, const T dyidyi, const T dzidzi, 
          const int itot, const int jtot, const int ktot) 

ctypedef fused float_t: 
    cython.float 
    cython.double 

@cython.boundscheck(False) 
@cython.wraparound(False) 
def diff(np.ndarray[float_t, ndim=3, mode="c"] at not None, 
     np.ndarray[float_t, ndim=3, mode="c"] a not None, 
     float_t visc, float_t dxidxi, float_t dyidyi, float_t dzidzi): 
    cdef int ktot, jtot, itot 
    ktot, jtot, itot = at.shape[0], at.shape[1], at.shape[2] 
    diff_cpp(&at[0,0,0], &a[0,0,0], visc, dxidxi, dyidyi, dzidzi, itot, jtot, ktot) 
    return None 
+0

juste spitballing, avez-vous essayé de faire un typedef pour les instanciations spécifiques de modèle, et donner ce nom non-modèle à python? –

Répondre

1

Deux notes:

  1. Cython supporte C++ modèle (http://docs.cython.org/en/latest/src/userguide/wrapping_CPlusPlus.html)
  2. Cython a types condensés (http://docs.cython.org/en/latest/src/userguide/fusedtypes.html)

Un exemple:

// lib.cpp 
template<typename T> 
T arr_sum(T *arr, size_t size) 
{ 
    T temp=0; 
    for (size_t i=0; i != size; ++i){ 
     temp += arr[i]; 
    } 
    return temp; 
} 

# lib_wrapper.pyx 
cimport cython 

ctypedef fused float_t: 
    cython.float 
    cython.double 

cdef extern from "lib.cpp" nogil: 
    T arr_sum[T](T *arr, size_t size) 

def py_arr_sum(float_t[:] arr not None): 
    print(sizeof(arr[0])) # check the element size 
    return arr_sum(&arr[0], arr.shape[0]) 

# use.py 
import numpy as np 
from lib_wrapper import py_arr_sum 

print(py_arr_sum(np.array([1,2,3], dtype=np.float32))) 
print(py_arr_sum(np.array([1,2,3], dtype=np.float64))) 
print(py_arr_sum(np.array([1,2,3], dtype=np.int32))) # oops 
+0

Je ne connaissais pas ces types fusionnés. Cela semble plutôt génial. – Chiel