我可以创建一个 PyObject*(numpy.float32)吗

2 投票
1 回答
709 浏览
提问于 2025-04-17 11:09

我正在尝试在C语言中实现一个函数(扩展Python),目的是返回一个numpy.float32的数据类型。请问真的可以创建一个对象并返回它,使得在Python中调用这个函数返回的对象是numpy.float32的实例吗?

(C扩展)

PyObject *numpyFloatFromFloat(float d)
{
   ret = SomeAPICall(d)
   return ret;
}

(在Python中)

a = something_special()

type(a)
-> numpy.float32

目前为止,我尝试使用参考文档中记录的API,结果都是创建一个数组,返回的是numpy.ndarray。而使用数据类型时,得到的是C语言的float类型,这在Python中会转换成double。出于某种我不知道的原因,我真的需要在这个函数的最后得到一个实际的IEEE 754 float32。

到目前为止的解决方案:

something.pyx:

cdef extern from "float_gen.h"
    float special_action(void)

def numpy_float_interface():
    return numpy.float32(special_action())

float_gen.h

static inline float special_action() { return 1.0; }

我在这里没有看到数据丢失,但我不能完全确定。我知道numpy.float32在C语言中被当作float或float32_t来处理,所以假设我在pyx文件中调用special_action时,它没有被转换成double(就像Python那样),那么应该是没有损失的。

编辑 最终的解决方案与我想的很不一样,我只需要理解如何正确地使用numpy库在C中扩展Python。

下面的代码只是返回一个np.float32(32)

static PyObject *get_float(PyObject *self, PyObject *args) {
    float v = 32;
    PyObject *np_float32_val = NULL;
    PyArray_Descr *descr = NULL;
    if(! PyArg_ParseTuple(args, ""))
        return NULL;
    if(! (descr = PyArray_DescrFromType(NPY_FLOAT32))) {
        PyErr_SetString(PyExc_TypeError, "Improper descriptor");
        return NULL;
    }

    np_float32_val = PyArray_Scalar(&v, descr, NULL);
    printf("%lu\n", np_float32_val->ob_refcnt);
    return np_float32_val;
}

1 个回答

1

这个简单的模块可以把C语言中的浮点数转换成np.int32类型。其实,cdef float并不是必须的,因为np.float32()会自动把你给它的任何东西转换成np.float32类型。

test_mod.pyx

import numpy as np
def fucn():
    cdef float a
    a = 1
    return np.float32(a)

tester.py

import pyximport
pyximport.install()
import test_mod

a = test_mod.func()
print type(a) # <type 'numpy.float32'>

撰写回答