@@ -107,39 +107,52 @@ Export API
107
107
108
108
Export of a Python :class:`int` object.
109
109
110
- .. c:struct:: digit_array
110
+ There are two cases:
111
111
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.
114
117
115
- .. c:member:: Py_ssize_t ndigits
118
+ .. c:member:: int64_t value
116
119
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``.
118
122
119
- .. c:member:: const void *digits
123
+ .. c:member:: uint8_t negative
120
124
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``.
122
127
123
- .. c:member:: uint8_t negative
128
+ .. c:member:: Py_ssize_t ndigits
124
129
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.
126
141
127
142
128
143
.. c:function:: int PyLong_Export(PyObject *obj, PyLongExport *export)
129
144
130
145
Export a Python :class: `int ` object.
131
146
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.
139
149
140
150
This function always succeeds if *obj * is a Python :class: `int ` object or a
141
151
subclass.
142
152
153
+ If *export->digits * is not ``NULL ``, :c:func: `PyLong_FreeExport ` must be
154
+ called when the export is no longer needed.
155
+
143
156
144
157
On CPython 3.14, no memory copy is needed in :c:func: `PyLong_Export `, it's just
145
158
a thin wrapper to expose Python :class: `int ` internal digits array.
@@ -254,29 +267,32 @@ Code::
254
267
static void
255
268
mpz_set_PyLong(mpz_t z, PyObject *obj)
256
269
{
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);
262
280
}
263
281
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);
274
295
}
275
- PyLong_FreeExport(&long_export);
276
- break;
277
- default:
278
- PyLong_FreeExport(&long_export);
279
- abort(); /* new CPython release came with a new format */
280
296
}
281
297
}
282
298
}
0 commit comments