classification
Title: PyLong_AS_LONG missing from longobject.h
Type: Stage: resolved
Components: C API Versions: Python 2.7
process
Status: closed Resolution: out of date
Dependencies: Superseder:
Assigned To: Nosy List: ngie, petr.viktorin, serhiy.storchaka
Priority: normal Keywords:

Created on 2020-02-26 18:19 by ngie, last changed 2020-03-05 02:48 by petr.viktorin. This issue is now closed.

Messages (10)
msg362705 - (view) Author: Enji Cooper (ngie) * Date: 2020-02-26 18:19
While trying to port python 2 C extension code forward to python 3, I noticed that the python 2.6 PyInt -> PyLong unification lacks a forward-compatible API for PyLong_AS_LONG.

I'm not sure if this was intentional, but it is a slightly annoying wicket to deal with when forward C extension code that needs to straddle 2 and 3 for a period of time.
msg362706 - (view) Author: Enji Cooper (ngie) * Date: 2020-02-26 18:21
For the record, some projects (like Cython, pywin32) worked around this by adding a preprocessor alias, PyLong_AS_LONG -> PyInt_AS_LONG with python 2.x.
msg362707 - (view) Author: Enji Cooper (ngie) * Date: 2020-02-26 18:23
For the record, this seems like it might be the only discrepancy, per the py3c project's exported PyInt APIs:

$ for api in `awk '$2 ~ /^PyInt/ { print $3 }' include/py3c/compat.h`; do grep -q $api /usr/include/python2.7/longobject.h || echo $api; done
PyLong_AS_LONG
msg362708 - (view) Author: Enji Cooper (ngie) * Date: 2020-02-26 18:29
Workaround PR posted here: https://github.com/encukou/py3c/pull/28
msg362709 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2020-02-26 18:34
Python 2 is no longer supported.
msg362713 - (view) Author: Enji Cooper (ngie) * Date: 2020-02-26 19:00
@serhiy.storchaka: understood. Figured this would be a good errata note for others to potentially find in the future.
msg362727 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2020-02-26 20:02
The reason why there was the PyInt_AS_LONG macro is that it is very simple and efficient. It never fails, because the value of the int object always fits in the C long. PyInt_AsLong is much slower. If you know that the object is int, you can use PyInt_AS_LONG for performance and simplicity.

In contrary, converting the long object to the C long value requires a loop and it can overflow. There is no reason to implement it as a macro. You can use the PyLong_AsLong function.
msg362749 - (view) Author: Enji Cooper (ngie) * Date: 2020-02-26 22:26
PyInt_AS_LONG doesn't exist on python 3, however:

$ grep -r PyInt_AS_LONG /usr/include/
[/usr/include/python2.7/intobject.h:#define PyInt_AS_LONG(op) (((PyIntObject *)(op))->ob_ival)

The code smell for the pieces that use PyInt_AS_LONG seems a bit questionable since they're used as array indexes; I'll poke a bit more and look at using one of the other sets of C APIs instead in our project.
msg363365 - (view) Author: Enji Cooper (ngie) * Date: 2020-03-04 17:49
> The reason why there was the PyInt_AS_LONG macro is that it is very simple and efficient. It never fails, because the value of the int object always fits in the C long. PyInt_AsLong is much slower. If you know that the object is int, you can use PyInt_AS_LONG for performance and simplicity.

Another note: this assertion holds generally true with contemporary hardware architectures (sizeof(long long) != sizeof(int)), but there are still 32-bit hardware/software architectures (ex: non-ARM64 capable ARM arches, i386, powerpc 32-bit, etc) that violate this constraint. 32-bit architectures are at risk of overflow with 32-bit values.
msg363414 - (view) Author: Petr Viktorin (petr.viktorin) * (Python committer) Date: 2020-03-05 02:48
No, in Python 2 the PyInt object (`int` in Python 2) always did fit into a C long -- that was the underlying storage. If it didn't fit, a PyLong object (`long` in Python 2) was used.

Python 3 doesn't have PyInt, it only has PyLong (`int` in Python 3).
History
Date User Action Args
2020-03-05 02:48:05petr.viktorinsetnosy: + petr.viktorin
messages: + msg363414
2020-03-04 17:49:45ngiesetmessages: + msg363365
2020-02-26 22:26:24ngiesetmessages: + msg362749
2020-02-26 20:02:42serhiy.storchakasetmessages: + msg362727
2020-02-26 19:00:45ngiesetmessages: + msg362713
2020-02-26 18:34:31serhiy.storchakasetstatus: open -> closed

nosy: + serhiy.storchaka
messages: + msg362709

resolution: out of date
stage: resolved
2020-02-26 18:29:36ngiesetmessages: + msg362708
2020-02-26 18:23:27ngiesetmessages: + msg362707
2020-02-26 18:21:11ngiesetmessages: + msg362706
2020-02-26 18:19:28ngiecreate