2017-09-02 1 views
0

TLDR: Comment définir la fonction is_float_object ci-dessous en cython pur?Utilisation de PyArray_IsScalar de Numpy en Cython

J'essaie de comprendre quelques fonctions dans pandas._libs qui sont définies dans pandas/_libs/src/numpy_helper.h et exposées via pandas/_libs/src/util.pxd. AFAICT ma confusion est liée à ne pas avoir d'intuition pour les espaces de noms dans le fichier .h.

Prenez is_float_object comme exemple. Ceci est défini dans numpy_helper.h comme

#include "Python.h" 
#include "numpy/arrayobject.h" 
#include "numpy/arrayscalars.h" 
[...] 

PANDAS_INLINE int is_float_object(PyObject* obj) { 
    return (PyFloat_Check(obj) || PyArray_IsScalar(obj, Floating)); 
} 

Je ne peux pas savoir où Floating est défini, comment il est entré dans l'espace de noms, et quel type de cdef extern from ... je dois utiliser pour l'obtenir dans un fichier cython.

PyArray_IsScalar est défini dans numpy/ndarrayobject.h:

#define PyArray_IsScalar(obj, cls)          \ 
    (PyObject_TypeCheck(obj, &Py##cls##ArrType_Type)) 

Il y a un commentaire dans Pandas/_libs/src/numpy.pxd qui me fait penser à la "##" signifie quelque chose de magique est en jeu:

# Cannot be supported due to ## ## in macro: 
# bint PyArray_IsScalar(object, verbatim work) 

Où est défini Floating? Que faudrait-il pour définir cette fonction directement dans Cython sans avoir besoin du fichier intermédiaire numpy_helper.h?

Répondre

2

## est une concaténation de préprocesseur C. Floating ne figure dans aucun espace de noms mais est simplement utilisé dans une concaténation de chaîne par le préprocesseur C. La section PyArray_IsScalar(obj, Floating) est traduit par le préprocesseur C soit:

(PyObject_TypeCheck(obj, &PyFloatingArrType_Type)) 

Si vous souhaitez définir le is_float_object dans Cython vous feriez cette concaténation vous:

from cpython cimport PyFloat_Check, PyObject_TypeCheck, PyTypeObject 

cdef extern from "numpy/arrayobject.h": 
    PyTypeObject PyFloatingArrType_Type 

cdef int is_float_object(obj): 
    return (PyFloat_Check(obj) or (PyObject_TypeCheck(obj, &PyFloatingArrType_Type))); 

(le cdef extern from "numpy/arrayobject.h" est un peu une estimation, mais je pense que cela vient de là)

+0

Merci d'avoir regardé cela. J'ai encore quelques permutations à essayer, mais jusqu'à présent cela mène à des erreurs de segmenter. Il semble qu'il ne vérifie pas si PyFloatingArrType_Type existe avant d'essayer d'appeler la fonction. Cela semble être le contraire de ce que j'attendrais d'un langage de compilation à faire. Est-ce que j'interprète cela incorrectement? – user2957943

+0

Il ressemble à ndarrayobject.h #include __multiarray_api.h, qui étiquette PyFloatingArrType_Type avec NPY_NO_EXPORT. Je suppose que cela signifie que je n'ai pas de chance. https://github.com/explosion/thinc/blob/master/include/numpy/__multiarray_api.h#L112 – user2957943

+0

Je suppose que vous devez exécuter 'numpy.import_array()' en premier. 'PyFloatingArrType_Type' est probablement une variable globale qui n'est initialisée que par le code d'importation du module. Il existe à la compilation mais n'a pas de valeur valide jusqu'à son initialisation. – DavidW