PyAPI: replace PyC_FromArray with typed functions
This was meant to be generic but introduced possible type errors and unnecessary complication. Replace with typed PyC_Tuple_PackArray_* functions. Also add PyC_Tuple_Pack_* macro which replaces some uses of Py_BuildValue, with the advantage of not having to parse a string.
This commit is contained in:
@@ -127,54 +127,52 @@ int PyC_AsArray(
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Typed Tuple Packing
|
||||
*
|
||||
* \note See #PyC_Tuple_Pack_* macros that take multiple arguments.
|
||||
*
|
||||
* \{ */
|
||||
|
||||
/* array utility function */
|
||||
PyObject *PyC_FromArray(const void *array, int length, const PyTypeObject *type,
|
||||
const bool is_double, const char *error_prefix)
|
||||
PyObject *PyC_Tuple_PackArray_F32(const float *array, uint len)
|
||||
{
|
||||
PyObject *tuple;
|
||||
int i;
|
||||
|
||||
tuple = PyTuple_New(length);
|
||||
|
||||
/* for each type */
|
||||
if (type == &PyFloat_Type) {
|
||||
if (is_double) {
|
||||
const double *array_double = array;
|
||||
for (i = 0; i < length; ++i) {
|
||||
PyTuple_SET_ITEM(tuple, i, PyFloat_FromDouble(array_double[i]));
|
||||
}
|
||||
}
|
||||
else {
|
||||
const float *array_float = array;
|
||||
for (i = 0; i < length; ++i) {
|
||||
PyTuple_SET_ITEM(tuple, i, PyFloat_FromDouble(array_float[i]));
|
||||
}
|
||||
}
|
||||
PyObject *tuple = PyTuple_New(len);
|
||||
for (uint i = 0; i < len; i++) {
|
||||
PyTuple_SET_ITEM(tuple, i, PyFloat_FromDouble(array[i]));
|
||||
}
|
||||
else if (type == &PyLong_Type) {
|
||||
/* could use is_double for 'long int' but no use now */
|
||||
const int *array_int = array;
|
||||
for (i = 0; i < length; ++i) {
|
||||
PyTuple_SET_ITEM(tuple, i, PyLong_FromLong(array_int[i]));
|
||||
}
|
||||
}
|
||||
else if (type == &PyBool_Type) {
|
||||
const int *array_bool = array;
|
||||
for (i = 0; i < length; ++i) {
|
||||
PyTuple_SET_ITEM(tuple, i, PyBool_FromLong(array_bool[i]));
|
||||
}
|
||||
}
|
||||
else {
|
||||
Py_DECREF(tuple);
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"%s: internal error %s is invalid",
|
||||
error_prefix, type->tp_name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return tuple;
|
||||
}
|
||||
|
||||
PyObject *PyC_Tuple_PackArray_I32(const int *array, uint len)
|
||||
{
|
||||
PyObject *tuple = PyTuple_New(len);
|
||||
for (uint i = 0; i < len; i++) {
|
||||
PyTuple_SET_ITEM(tuple, i, PyLong_FromLong(array[i]));
|
||||
}
|
||||
return tuple;
|
||||
}
|
||||
|
||||
PyObject *PyC_Tuple_PackArray_I32FromBool(const int *array, uint len)
|
||||
{
|
||||
PyObject *tuple = PyTuple_New(len);
|
||||
for (uint i = 0; i < len; i++) {
|
||||
PyTuple_SET_ITEM(tuple, i, PyBool_FromLong(array[i]));
|
||||
}
|
||||
return tuple;
|
||||
}
|
||||
|
||||
PyObject *PyC_Tuple_PackArray_Bool(const bool *array, uint len)
|
||||
{
|
||||
PyObject *tuple = PyTuple_New(len);
|
||||
for (uint i = 0; i < len; i++) {
|
||||
PyTuple_SET_ITEM(tuple, i, PyBool_FromLong(array[i]));
|
||||
}
|
||||
return tuple;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/**
|
||||
* Caller needs to ensure tuple is uninitialized.
|
||||
* Handy for filling a tuple with None for eg.
|
||||
|
@@ -45,8 +45,21 @@ int PyC_AsArray_FAST(
|
||||
int PyC_AsArray(
|
||||
void *array, PyObject *value, const Py_ssize_t length,
|
||||
const PyTypeObject *type, const bool is_double, const char *error_prefix);
|
||||
PyObject * PyC_FromArray(const void *array, int length, const PyTypeObject *type,
|
||||
const bool is_double, const char *error_prefix);
|
||||
|
||||
PyObject *PyC_Tuple_PackArray_F32(const float *array, uint len);
|
||||
PyObject *PyC_Tuple_PackArray_I32(const int *array, uint len);
|
||||
PyObject *PyC_Tuple_PackArray_I32FromBool(const int *array, uint len);
|
||||
PyObject *PyC_Tuple_PackArray_Bool(const bool *array, uint len);
|
||||
|
||||
#define PyC_Tuple_Pack_F32(...) \
|
||||
PyC_Tuple_PackArray_F32(((const float []){__VA_ARGS__}), (sizeof((const float []){__VA_ARGS__}) / sizeof(float)))
|
||||
#define PyC_Tuple_Pack_I32(...) \
|
||||
PyC_Tuple_PackArray_I32(((const int []){__VA_ARGS__}), (sizeof((const int []){__VA_ARGS__}) / sizeof(int)))
|
||||
#define PyC_Tuple_Pack_I32FromBool(...) \
|
||||
PyC_Tuple_PackArray_I32FromBool(((const int []){__VA_ARGS__}), (sizeof((const int []){__VA_ARGS__}) / sizeof(int)))
|
||||
#define PyC_Tuple_Pack_Bool(...) \
|
||||
PyC_Tuple_PackArray_Bool(((const bool []){__VA_ARGS__}), (sizeof((const bool []){__VA_ARGS__}) / sizeof(bool)))
|
||||
|
||||
void PyC_Tuple_Fill(PyObject *tuple, PyObject *value);
|
||||
void PyC_List_Fill(PyObject *list, PyObject *value);
|
||||
|
||||
|
Reference in New Issue
Block a user