# C stable api PY\_SSIZE\_T\_CLEAN error

**URL:** <https://discuss.python.org/t/c-stable-api-py-ssize-t-clean-error/80159>\
**Category:** Python Help\
**Created:** [February 10, 2025, 10:07am UTC](https://discuss.python.org/t/c-stable-api-py-ssize-t-clean-error/80159 "2025-02-10T10:07:47Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![replabrobin](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/replabrobin/32/8686_2.png) [@replabrobin](https://discuss.python.org/u/replabrobin)\
**Post date:** [February 10, 2025, 10:07am UTC](https://discuss.python.org/t/c-stable-api-py-ssize-t-clean-error/80159/1 "2025-02-10T10:07:47Z")

</div>

I maintain an optional reportlab c extension [rl-accel · PyPI](https://pypi.org/project/rl-accel/)

It has been working fine in Python 3.7 - 3.12 when compiled as a stable api 3.7 extension.

Problems were observed using this in 3.13 and 3.14 and I was advised that changes had made some commen macros behave differently. Compiling with a later python would improve things although speed might be reduced.

I now observe the following error when using a Python 3.14/3.13 compiled extension with python \<=3.12

> File “/home/robin/devel/reportlab/reportlab/pdfbase/ttfonts.py”, line 384, in makeStream  
> checksum = calcChecksum(data)  
> ^^^^^^^^^^^^^^^^^^  
> SystemError: PY\_SSIZE\_T\_CLEAN macro must be defined for ‘#’ formats

I thing the error comes from this function

```python
static PyObject *ttfonts_calcChecksum(PyObject *module, PyObject* args)
{
	unsigned char	*data;
	Py_ssize_t dataLen;
	unsigned long	Sum = 0L;
	unsigned char	*EndPtr;
	unsigned long n;
	int leftover;

	if (!PyArg_ParseTuple(args, "s#:calcChecksum", &data, &dataLen)) return NULL;

```

The source code contains this which does define PY\_SSIZE\_T\_CLEAN

```python
#define PY_SSIZE_T_CLEAN
#include "Python.h"
#include <stdlib.h>
#include <math.h>

```

So I don’t know how to fix.

How I can get a module thet covers 3.9 - 3.14?

---

<div class="post-metadata">

**Author:** ![ngoldbaum](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/ngoldbaum/32/12276_2.png) [@ngoldbaum](https://discuss.python.org/u/ngoldbaum)\
**Post date:** [February 10, 2025, 2:18pm UTC](https://discuss.python.org/t/c-stable-api-py-ssize-t-clean-error/80159/2 "2025-02-10T14:18:16Z")

</div>

It might help if you can create a stand-alone project that triggers the issue or point to a branch in your project’s VCS someone could look at. I don’t immediately see anything wrong in the code you shared above.

---

<div class="post-metadata">

**Author:** ![replabrobin](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/replabrobin/32/8686_2.png) [@replabrobin](https://discuss.python.org/u/replabrobin)\
**Post date:** [February 10, 2025, 3:22pm UTC](https://discuss.python.org/t/c-stable-api-py-ssize-t-clean-error/80159/3 "2025-02-10T15:22:54Z")

</div>

I will try ripping out the checksum code into a small project and see if that fails across 3.13\<-\>3.12.

A quick inspection of the 3.13 code indicates no usage of that define.

The rl-accel package is here branch checksum-issue

[rl-accel: Summary](https://hg.reportlab.com/hg-public/rl-accel/) mirror is [GitHub - MrBitBucket/rl-accel-mirror](https://github.com/MrBitBucket/rl-accel-mirror)

There is a runner script in the tests directory; I use two pythons win the script

`PYTHONS=(${EARLYPYTHON:-~/bin/python312} ${LATEPYTHON:-~/bin/python313})`

you can mess with env vars EARLYPYTHON & LATEPYTHON to set those.

When run it downloads from the git mirror and runs a test script. for me things look like this

```python
extension built with 312 running tests/testcs.py with python312
_rl_accel.abi3.so-->build/lib.linux-x86_64-cpython-312/_rl_accel.abi3.so
3.12.9 (main, Feb 5 2025, 09:12:22) [GCC 14.2.1 20240910]
#############################################################
calcChecksum(b"Hello cruel world!")=142323306

#############################################################
extension built with 312 running tests/testcs.py with python313
_rl_accel.abi3.so-->build/lib.linux-x86_64-cpython-312/_rl_accel.abi3.so
3.13.2 (main, Feb 5 2025, 09:44:21) [GCC 14.2.1 20240910]
#############################################################
calcChecksum(b"Hello cruel world!")=142323306

#############################################################
extension built with 313 running tests/testcs.py with python312
_rl_accel.abi3.so-->build/lib.linux-x86_64-cpython-313/_rl_accel.abi3.so
3.12.9 (main, Feb 5 2025, 09:12:22) [GCC 14.2.1 20240910]
#############################################################
Traceback (most recent call last):
  File "/home/robin/devel/reportlab/REPOS/rl-accel/tests/tmp/rl-accel-mirror/tests/testcs.py", line 4, in <module>
    print(f'{calcChecksum(b"Hello cruel world!")=}')
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
SystemError: PY_SSIZE_T_CLEAN macro must be defined for '#' formats

```

---

<div class="post-metadata">

**Author:** ![da-woods](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/da-woods/32/7507_2.png) [@da-woods](https://discuss.python.org/u/da-woods)\
**Post date:** [February 10, 2025, 10:53pm UTC](https://discuss.python.org/t/c-stable-api-py-ssize-t-clean-error/80159/4 "2025-02-10T22:53:59Z")

</div>

In the older versions, it looks like `PY_SSIZE_T_CLEAN` defined `PyArg_ParseTuple` as `_PyArg_ParseTuple_SizeT`.

`_PyArg_ParseTuple_SizeT` no longer appears in the headers, but is part of the stable ABI so continues to be part of the Python library.

Therefore what you want to do is use `_PyArg_ParseTuple_SizeT` instead (on all Python versions). Just copy the declaration of it:

```python
PyAPI_FUNC(int)
_PyArg_ParseTuple_SizeT(PyObject *args, const char *format, ...);

```

to assure the C compiler that _it really does exist, somewhere_, and use that instead of `PyArg_ParseTuple`.

---

<div class="post-metadata">

**Author:** ![replabrobin](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/replabrobin/32/8686_2.png) [@replabrobin](https://discuss.python.org/u/replabrobin)\
**Post date:** [February 11, 2025, 8:32am UTC](https://discuss.python.org/t/c-stable-api-py-ssize-t-clean-error/80159/5 "2025-02-11T08:32:56Z")

</div>

Thanks, I’ll give that a try.

---

<div class="post-metadata">

**Author:** ![replabrobin](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/replabrobin/32/8686_2.png) [@replabrobin](https://discuss.python.org/u/replabrobin)\
**Post date:** [February 11, 2025, 9:33am UTC](https://discuss.python.org/t/c-stable-api-py-ssize-t-clean-error/80159/6 "2025-02-11T09:33:31Z")

</div>

Thanks for the assist. Your fix does work, but it seems a bit dangerous to rely on something which is not exposed or even mentioned in the C ABI documentation.

---

<div class="post-metadata">

**Author:** ![mxmlnkn](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/mxmlnkn/32/28872_2.png) [@mxmlnkn](https://discuss.python.org/u/mxmlnkn)\
**Post date:** [June 28, 2025, 6:15am UTC](https://discuss.python.org/t/c-stable-api-py-ssize-t-clean-error/80159/7 "2025-06-28T06:15:55Z")

</div>

I have the same issue and the same qualms about relying on the undocumented `_PyArg_ParseTuple_SizeT` function. A full reproducer is in [this branch](https://github.com/mxmlnkn/fast-zip-decryption/tree/py_ssize_t-issue). The abi3 wheel built with Python 3.13 will fail the test with Python 3.9. My workaround will be to build the abi3 wheel with Python 3.12 until it is EOL.
