Question

I am trying to implement a function in C (Extending Python) to return a numpy.float32 data type. Is it possible to actually create an object and return it, such that in python the object returned from calling the function is an instance of numpy.float32 ?

(C Extension)

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

(in python)

a = something_special()

type(a)
-> numpy.float32

Right now all attempts at using the API documented in the reference documentation illustrate how to make an Array which yields a numpy.ndarray, and so far using the data types yields a C-type float which converts to a double in python. And for some reason that I'm unaware of, I really need an actual IEEE 754 float32 at the end of this function.

Solution thus far:

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

I don't see any loss in data here but I can't be certain. I know a numpy.float32 is treated as a C float or float32_t so assuming when I call special_action in the pyx file that it doesn't convert it to a double (as python does) it should be lossless.

Edit The ultimate solution was very different, I just had to understand how to properly extend Python in C with the numpy library.

Below just returns a 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;
}
Was it helpful?

Solution

This simple module returns np.int32 from a C float. The cdef float isn't really necessary as np.float32() should coerce whatever you give to it to a 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'>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top