Use PyCapsule in _imagingmath

This commit is contained in:
Aleksandr Karpinskii 2024-09-02 01:24:51 +04:00
parent 44c2ff3f0b
commit 2303c063cb
2 changed files with 94 additions and 55 deletions

View File

@ -65,7 +65,7 @@ class _Operand:
except AttributeError as e: except AttributeError as e:
msg = f"bad operand type for '{op}'" msg = f"bad operand type for '{op}'"
raise TypeError(msg) from e raise TypeError(msg) from e
_imagingmath.unop(op, out.im.id, im_1.im.id) _imagingmath.unop(op, out.im.ptr, im_1.im.ptr)
else: else:
# binary operation # binary operation
im_2 = self.__fixup(im2) im_2 = self.__fixup(im2)
@ -93,7 +93,7 @@ class _Operand:
except AttributeError as e: except AttributeError as e:
msg = f"bad operand type for '{op}'" msg = f"bad operand type for '{op}'"
raise TypeError(msg) from e raise TypeError(msg) from e
_imagingmath.binop(op, out.im.id, im_1.im.id, im_2.im.id) _imagingmath.binop(op, out.im.ptr, im_1.im.ptr, im_2.im.ptr)
return _Operand(out) return _Operand(out)
# unary operators # unary operators

View File

@ -23,6 +23,9 @@
#define MAX_INT32 2147483647.0 #define MAX_INT32 2147483647.0
#define MIN_INT32 -2147483648.0 #define MIN_INT32 -2147483648.0
#define MATH_FUNC_UNOP_MAGIC "Pillow Math unary func"
#define MATH_FUNC_BINOP_MAGIC "Pillow Math binary func"
#define UNOP(name, op, type) \ #define UNOP(name, op, type) \
void name(Imaging out, Imaging im1) { \ void name(Imaging out, Imaging im1) { \
int x, y; \ int x, y; \
@ -168,15 +171,28 @@ _unop(PyObject *self, PyObject *args) {
Imaging im1; Imaging im1;
void (*unop)(Imaging, Imaging); void (*unop)(Imaging, Imaging);
Py_ssize_t op, i0, i1; PyObject *op, *i0, *i1;
if (!PyArg_ParseTuple(args, "nnn", &op, &i0, &i1)) { if (!PyArg_ParseTuple(args, "OOO", &op, &i0, &i1)) {
return NULL; return NULL;
} }
out = (Imaging)i0; if (!PyCapsule_IsValid(op, MATH_FUNC_UNOP_MAGIC)) {
im1 = (Imaging)i1; PyErr_Format(
PyExc_TypeError, "Expected PyCapsule with '%s' name.", MATH_FUNC_UNOP_MAGIC
);
return NULL;
}
if (!PyCapsule_IsValid(i0, IMAGING_MAGIC) ||
!PyCapsule_IsValid(i1, IMAGING_MAGIC)) {
PyErr_Format(
PyExc_TypeError, "Expected PyCapsule with '%s' name.", IMAGING_MAGIC
);
return NULL;
}
unop = (void *)op; unop = (void *)PyCapsule_GetPointer(op, MATH_FUNC_UNOP_MAGIC);
out = (Imaging)PyCapsule_GetPointer(i0, IMAGING_MAGIC);
im1 = (Imaging)PyCapsule_GetPointer(i1, IMAGING_MAGIC);
unop(out, im1); unop(out, im1);
@ -191,16 +207,30 @@ _binop(PyObject *self, PyObject *args) {
Imaging im2; Imaging im2;
void (*binop)(Imaging, Imaging, Imaging); void (*binop)(Imaging, Imaging, Imaging);
Py_ssize_t op, i0, i1, i2; PyObject *op, *i0, *i1, *i2;
if (!PyArg_ParseTuple(args, "nnnn", &op, &i0, &i1, &i2)) { if (!PyArg_ParseTuple(args, "OOOO", &op, &i0, &i1, &i2)) {
return NULL; return NULL;
} }
out = (Imaging)i0; if (!PyCapsule_IsValid(op, MATH_FUNC_BINOP_MAGIC)) {
im1 = (Imaging)i1; PyErr_Format(
im2 = (Imaging)i2; PyExc_TypeError, "Expected PyCapsule with '%s' name.", MATH_FUNC_BINOP_MAGIC
);
return NULL;
}
if (!PyCapsule_IsValid(i0, IMAGING_MAGIC) ||
!PyCapsule_IsValid(i1, IMAGING_MAGIC) ||
!PyCapsule_IsValid(i2, IMAGING_MAGIC)) {
PyErr_Format(
PyExc_TypeError, "Expected PyCapsule with '%s' name.", IMAGING_MAGIC
);
return NULL;
}
binop = (void *)op; binop = (void *)PyCapsule_GetPointer(op, MATH_FUNC_BINOP_MAGIC);
out = (Imaging)PyCapsule_GetPointer(i0, IMAGING_MAGIC);
im1 = (Imaging)PyCapsule_GetPointer(i1, IMAGING_MAGIC);
im2 = (Imaging)PyCapsule_GetPointer(i2, IMAGING_MAGIC);
binop(out, im1, im2); binop(out, im1, im2);
@ -213,8 +243,17 @@ static PyMethodDef _functions[] = {
}; };
static void static void
install(PyObject *d, char *name, void *value) { install_unary(PyObject *d, char *name, void *func) {
PyObject *v = PyLong_FromSsize_t((Py_ssize_t)value); PyObject *v = PyCapsule_New(func, MATH_FUNC_UNOP_MAGIC, NULL);
if (!v || PyDict_SetItemString(d, name, v)) {
PyErr_Clear();
}
Py_XDECREF(v);
}
static void
install_binary(PyObject *d, char *name, void *func) {
PyObject *v = PyCapsule_New(func, MATH_FUNC_BINOP_MAGIC, NULL);
if (!v || PyDict_SetItemString(d, name, v)) { if (!v || PyDict_SetItemString(d, name, v)) {
PyErr_Clear(); PyErr_Clear();
} }
@ -225,50 +264,50 @@ static int
setup_module(PyObject *m) { setup_module(PyObject *m) {
PyObject *d = PyModule_GetDict(m); PyObject *d = PyModule_GetDict(m);
install(d, "abs_I", abs_I); install_unary(d, "abs_I", abs_I);
install(d, "neg_I", neg_I); install_unary(d, "neg_I", neg_I);
install(d, "add_I", add_I); install_binary(d, "add_I", add_I);
install(d, "sub_I", sub_I); install_binary(d, "sub_I", sub_I);
install(d, "diff_I", diff_I); install_binary(d, "diff_I", diff_I);
install(d, "mul_I", mul_I); install_binary(d, "mul_I", mul_I);
install(d, "div_I", div_I); install_binary(d, "div_I", div_I);
install(d, "mod_I", mod_I); install_binary(d, "mod_I", mod_I);
install(d, "min_I", min_I); install_binary(d, "min_I", min_I);
install(d, "max_I", max_I); install_binary(d, "max_I", max_I);
install(d, "pow_I", pow_I); install_binary(d, "pow_I", pow_I);
install(d, "invert_I", invert_I); install_unary(d, "invert_I", invert_I);
install(d, "and_I", and_I); install_binary(d, "and_I", and_I);
install(d, "or_I", or_I); install_binary(d, "or_I", or_I);
install(d, "xor_I", xor_I); install_binary(d, "xor_I", xor_I);
install(d, "lshift_I", lshift_I); install_binary(d, "lshift_I", lshift_I);
install(d, "rshift_I", rshift_I); install_binary(d, "rshift_I", rshift_I);
install(d, "eq_I", eq_I); install_binary(d, "eq_I", eq_I);
install(d, "ne_I", ne_I); install_binary(d, "ne_I", ne_I);
install(d, "lt_I", lt_I); install_binary(d, "lt_I", lt_I);
install(d, "le_I", le_I); install_binary(d, "le_I", le_I);
install(d, "gt_I", gt_I); install_binary(d, "gt_I", gt_I);
install(d, "ge_I", ge_I); install_binary(d, "ge_I", ge_I);
install(d, "abs_F", abs_F); install_unary(d, "abs_F", abs_F);
install(d, "neg_F", neg_F); install_unary(d, "neg_F", neg_F);
install(d, "add_F", add_F); install_binary(d, "add_F", add_F);
install(d, "sub_F", sub_F); install_binary(d, "sub_F", sub_F);
install(d, "diff_F", diff_F); install_binary(d, "diff_F", diff_F);
install(d, "mul_F", mul_F); install_binary(d, "mul_F", mul_F);
install(d, "div_F", div_F); install_binary(d, "div_F", div_F);
install(d, "mod_F", mod_F); install_binary(d, "mod_F", mod_F);
install(d, "min_F", min_F); install_binary(d, "min_F", min_F);
install(d, "max_F", max_F); install_binary(d, "max_F", max_F);
install(d, "pow_F", pow_F); install_binary(d, "pow_F", pow_F);
install(d, "eq_F", eq_F); install_binary(d, "eq_F", eq_F);
install(d, "ne_F", ne_F); install_binary(d, "ne_F", ne_F);
install(d, "lt_F", lt_F); install_binary(d, "lt_F", lt_F);
install(d, "le_F", le_F); install_binary(d, "le_F", le_F);
install(d, "gt_F", gt_F); install_binary(d, "gt_F", gt_F);
install(d, "ge_F", ge_F); install_binary(d, "ge_F", ge_F);
return 0; return 0;
} }