2017-09-02 51 views
0

TLDR:如何在純循環中定義is_float_object函數?在Cython中使用Numpy的PyArray_IsScalar

我想了解pandas._libs中的一些函數,這些函數在pandas/_libs/src/numpy_helper.h中定義並通過pandas/_libs/src/util.pxd公開。 AFAICT我的困惑與.h文件中的命名空間沒有直覺有關。

is_float_object爲例。這在numpy_helper.h

#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)); 
} 

我想不通的地方Floating的定義,它是如何鑽進命名空間中定義的,什麼類型的cdef extern from ...我需要用得到它變成一個用Cython文件。

PyArray_IsScalarnumpy/ndarrayobject.h定義:

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

中有大熊貓/ _libs/src目錄/ numpy.pxd這讓我想起了 「##」 是指一些特殊的魔力評論在作怪:

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

Floating哪裏定義?在不需要中間文件numpy_helper.h的情況下,直接在cython中定義這個函數需要什麼?

回答

2

##是C預處理器級聯。 Floating不在任何名稱空間中,但僅由C預處理器在字符串連接中使用。本節PyArray_IsScalar(obj, Floating)是由C預處理器翻譯爲:

(PyObject_TypeCheck(obj, &PyFloatingArrType_Type)) 

如果要定義在用Cython的is_float_object你應該這樣做級聯自己:

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))); 

(該cdef extern from "numpy/arrayobject.h"是有點一個猜測,但我認爲它來自那裏)

+0

謝謝你看看這個。我有更多的嘗試嘗試,但到目前爲止,這導致了段錯誤。好像它不檢查PyFloatingArrType_Type是否存在,直到實際嘗試調用該函數。這看起來與我期望編譯語言所做的相反。我解釋錯了嗎? – user2957943

+0

它看起來像ndarrayobject.h#包含__multiarray_api.h,它標記PyFloatingArrType_Type與NPY_NO_EXPORT。我猜這意味着我運氣不好。 https://github.com/explosion/thinc/blob/master/include/numpy/__multiarray_api.h#L112 – user2957943

+0

我懷疑你需要首先運行'numpy.import_array()'。 'PyFloatingArrType_Type'很可能是一個全局變量,它只能由模塊導入代碼初始化。它在編譯時存在,但在初始化之前沒有有效的值。 – DavidW