Skip to content

Commit d6ad15e

Browse files
committed
revert old PyLongExport & return type for PyLong_Export :(
1 parent 7753784 commit d6ad15e

File tree

1 file changed

+52
-36
lines changed

1 file changed

+52
-36
lines changed

peps/pep-0757.rst

Lines changed: 52 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -107,39 +107,52 @@ Export API
107107
108108
Export of a Python :class:`int` object.
109109
110-
.. c:struct:: digit_array
110+
There are two cases:
111111
112-
Export an integer as an array of digits; corresponds to
113-
:c:macro:`!PyLongExport_DigitArray` export type.
112+
* If :c:member:`digits` is ``NULL``, only use the :c:member:`value` member.
113+
Calling :c:func:`PyLong_FreeExport` is optional in this case.
114+
* If :c:member:`digits` is not ``NULL``, use :c:member:`negative`,
115+
:c:member:`ndigits` and :c:member:`digits` members.
116+
Calling :c:func:`PyLong_FreeExport` is mandatory in this case.
114117
115-
.. c:member:: Py_ssize_t ndigits
118+
.. c:member:: int64_t value
116119
117-
Number of digits in :c:member:`digits` array.
120+
The native integer value of the exported :class:`int` object.
121+
Only valid if :c:member:`digits` is ``NULL``.
118122
119-
.. c:member:: const void *digits
123+
.. c:member:: uint8_t negative
120124
121-
Read-only array of unsigned digits.
125+
1 if the number is negative, 0 otherwise.
126+
Only valid if :c:member:`digits` is not ``NULL``.
122127
123-
.. c:member:: uint8_t negative
128+
.. c:member:: Py_ssize_t ndigits
124129
125-
1 if the number is negative, 0 otherwise.
130+
Number of digits in :c:member:`digits` array.
131+
Only valid if :c:member:`digits` is not ``NULL``.
132+
133+
.. c:member:: const void *digits
134+
135+
Read-only array of unsigned digits. Can be ``NULL``.
136+
137+
If :c:member:`digits` not ``NULL``, a private field of the
138+
:c:struct:`PyLongExport` structure stores a strong reference to the Python
139+
:class:`int` object to make sure that that structure remains valid until
140+
:c:func:`PyLong_FreeExport()` is called.
126141
127142
128143
.. c:function:: int PyLong_Export(PyObject *obj, PyLongExport *export)
129144
130145
Export a Python :class:`int` object.
131146
132-
On success, set *\*export* and return an appropriate export type
133-
for the given value, see the :c:struct:`PyLongExport` struct.
134-
:c:func:`PyLong_FreeExport` must be called when the export is no
135-
longer needed. Currently the only available type is
136-
:c:macro:`!PyLongExport_DigitArray`.
137-
138-
On error, set an exception and return :c:macro:`!PyLongExport_Error`.
147+
On success, set *\*export* and return 0.
148+
On error, set an exception and return -1.
139149
140150
This function always succeeds if *obj* is a Python :class:`int` object or a
141151
subclass.
142152
153+
If *export->digits* is not ``NULL``, :c:func:`PyLong_FreeExport` must be
154+
called when the export is no longer needed.
155+
143156
144157
On CPython 3.14, no memory copy is needed in :c:func:`PyLong_Export`, it's just
145158
a thin wrapper to expose Python :class:`int` internal digits array.
@@ -254,29 +267,32 @@ Code::
254267
static void
255268
mpz_set_PyLong(mpz_t z, PyObject *obj)
256269
{
257-
int overflow;
258-
long value = PyLong_AsLongAndOverflow(obj, &overflow);
259-
260-
if (!overflow) {
261-
mpz_set_si(z, value);
270+
static PyLongExport long_export;
271+
272+
PyLong_Export(obj, &long_export);
273+
if (long_export.digits) {
274+
mpz_import(z, long_export.ndigits, int_digits_order, int_digit_size,
275+
int_endianness, int_nails, long_export.digits);
276+
if (long_export.negative) {
277+
mpz_neg(z, z);
278+
}
279+
PyLong_FreeExport(&long_export);
262280
}
263281
else {
264-
static PyLongExport long_export;
265-
const PyLongExport_Kind kind = PyLong_Export(obj, &long_export);
266-
267-
switch (kind) {
268-
case PyLongExport_DigitArray:
269-
mpz_import(z, long_export.digit_array.ndigits, int_digits_order,
270-
int_digit_size, int_endianness, int_nails,
271-
long_export.digit_array.digits);
272-
if (long_export.digit_array.negative) {
273-
mpz_neg(z, z);
282+
const int64_t value = long_export.value;
283+
284+
if (LONG_MIN <= value && value <= LONG_MAX) {
285+
mpz_set_si(z, value);
286+
}
287+
else {
288+
mpz_import(z, 1, -1, sizeof(int64_t), 0, 0, &value);
289+
if (value < 0) {
290+
mpz_t tmp;
291+
mpz_init(tmp);
292+
mpz_ui_pow_ui(tmp, 2, 64);
293+
mpz_sub(z, z, tmp);
294+
mpz_clear(tmp);
274295
}
275-
PyLong_FreeExport(&long_export);
276-
break;
277-
default:
278-
PyLong_FreeExport(&long_export);
279-
abort(); /* new CPython release came with a new format */
280296
}
281297
}
282298
}

0 commit comments

Comments
 (0)