Skip to content

docs: add optype.numpy.ctypeslib reference page - #581

Draft
Aniketsy wants to merge 12 commits into
jorenham:masterfrom
Aniketsy:fix-448
Draft

docs: add optype.numpy.ctypeslib reference page#581
Aniketsy wants to merge 12 commits into
jorenham:masterfrom
Aniketsy:fix-448

Conversation

@Aniketsy

Copy link
Copy Markdown
Contributor

fixes #448

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new reference page documenting the optype.numpy.ctypeslib module, which provides typed ctypes constructor reexports and abstract typing aliases for NumPy scalar-like C types (addressing the request in #448 to document this niche-but-existing API surface).

Changes:

  • Introduces docs/reference/numpy/ctypeslib.md describing the reexported ctypes constructors exposed by optype.numpy.ctypeslib.
  • Documents the module’s higher-level abstract typing aliases (CType, CScalar, Array, numeric families, etc.).

Comment thread docs/reference/numpy/ctypeslib.md Outdated
Comment thread docs/reference/numpy/ctypeslib.md Outdated
Comment thread docs/reference/numpy/ctypeslib.md Outdated
Comment thread docs/reference/numpy/ctypeslib.md Outdated
Comment thread docs/reference/numpy/ctypeslib.md Outdated
Aniketsy and others added 3 commits April 23, 2026 22:31
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@Aniketsy

Copy link
Copy Markdown
Contributor Author

@jorenham could you please re-review request from copilot, so that we can check if anything is missing. Thanks!

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 4 comments.

Comment thread docs/reference/numpy/ctypeslib.md Outdated
Comment thread docs/reference/numpy/ctypeslib.md Outdated
Comment thread docs/reference/numpy/ctypeslib.md Outdated
Comment thread docs/reference/numpy/ctypeslib.md Outdated
Comment thread docs/reference/index.md Outdated

@jorenham jorenham left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The navigation link is missing (see zensical.toml)

Comment thread docs/reference/numpy/ctypeslib.md Outdated
Comment thread docs/reference/numpy/ctypeslib.md Outdated
Comment thread docs/reference/numpy/ctypeslib.md Outdated
Comment thread docs/reference/numpy/ctypeslib.md Outdated
Comment thread docs/reference/numpy/ctypeslib.md Outdated
Comment thread docs/reference/numpy/ctypeslib.md Outdated
Comment thread docs/reference/numpy/ctypeslib.md Outdated
Comment thread docs/reference/numpy/ctypeslib.md Outdated
@Aniketsy

Aniketsy commented May 6, 2026

Copy link
Copy Markdown
Contributor Author

thanks for the review, this needs lot improvement, i'll take some time for this and update (maybe on sunday)

@Aniketsy

Copy link
Copy Markdown
Contributor Author

hoping did not miss anything, i'll try to verify once again from my side, as i think this is going to create pain for you to review 🙏 .

Aniketsy and others added 2 commits July 23, 2026 11:35
Signed-off-by: Aniket <148300120+Aniketsy@users.noreply.github.com>
@Aniketsy

Copy link
Copy Markdown
Contributor Author

hi @jorenham could you please ask copilot to review once .. so that we can proceed with this...

As i have asked claude(sonnet 4.6) to review and then improved .

@jorenham

Copy link
Copy Markdown
Owner

I cancelled my copilot subscription, but I'll have Claude Fable take a look 👌

@jorenham
jorenham self-requested a review July 23, 2026 21:09

@jorenham jorenham left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok I had Claude Fable 5 review this, and here's what it has to say:


Reviewed against the source (optype/numpy/ctypeslib.py, _ctypeslib.pyi) and the earlier review rounds.

Verified

  • All previous feedback is addressed: nav entries in zensical.toml and docs/reference/index.md, one row per alias, abstract aliases spelled out as explicit unions, notes column removed, ct. used consistently.
  • The ILP32/LP64/LLP64 aliasing table is correct; I checked the c_int/c_long/c_longlong and c_(s)size_t collapsing rules against ctypes directly.
  • The union tables match the definitions in the source, including the CScalar[int] invariance trick and the reason Bool sits outside Number.
  • Both example snippets typecheck (basedpyright), and the first one runs as written.

Wording issue

  • Abstract type aliases intro: "_CData has no runtime counterpart" isn't quite right. The class exists at runtime (it's c_int.mro()[2]); it just isn't importable by name from ctypes. And "These exist only for annotations" doesn't hold for CType/CScalar, which optype does export at runtime. Suggest rewording along the lines of "not importable from ctypes by name, and not meant to be instantiated".

Nits

  • The admonition says Object and Bool shadow builtins; they don't (the capitalization differs). The real collisions are typing.Generic and optype.numpy.Array, which means something different in the parent namespace. I'd trim the note to those two.
  • "There is no data model on which all four are distinct": the paragraph only names three types, so "four" is confusing.
  • NumPy version notes: "the distinction is not observable in practice" overstates it; c_void_p and c_size_t are distinct classes with different .value semantics. The source comment's "almost always equivalent" is the safer phrasing.
  • The heading "Several of these names are aliases of each other" reads as a sentence; something shorter like "Aliased names" would fit the page style better.

Out of scope, found while verifying

  • The runtime values in _ctypeslib.py are swapped relative to the stub: _, CType, CScalar, *_ = ct.c_int.mro() yields runtime CType = _SimpleCData and CScalar = _CData, while the .pyi declares the opposite. The doc correctly follows the stub, but this deserves a separate fix.

Otherwise accurate and complete. LGTM after the wording fix.


Pretty decent review IMO, right? I, at least, agree with the robot here.

RE: the out of scope issues it found; I'll look into that myself.

@jorenham

jorenham commented Jul 23, 2026

Copy link
Copy Markdown
Owner

Oh and one more thing; The page title looks a bit out-of-style in the NumPy menu:

Screenshot_2026-07-23_23-22-46

So something like ctypeslib submodule would be a better fit I think.

Also, maybe we should mention somewhere that this optype.numpy.ctypeslib module is called this way because it's related to numpy.ctypeslib (https://numpy.org/doc/stable/reference/routines.ctypeslib.html).

@Aniketsy

Copy link
Copy Markdown
Contributor Author

Thanks for the review, today i'll address these review points so that we can proceed

@Aniketsy

Copy link
Copy Markdown
Contributor Author

well this comment is off topic 😀

I've read the blog post of nominating you as a member in Python - Typing ... excited for results and seeing you as nominated .

atleast then could you please review my PRs there with light speed as there sometimes after being approved we don't know after how many months it get merged ( just kidding please ignore)

please ping me once results are out if i miss that ... i'm waiting ( so that i can congratulate) 😊


Also yesterday, I've explored typestats dasboard and opened small PR in matplotlib to increase type coverage , just curious in some projects there is 0 % coverage . Will they be interested in improving this or there are any limitations ( which is stopping them ).

@jorenham

Copy link
Copy Markdown
Owner

please ping me once results are out if i miss that ... i'm waiting ( so that i can congratulate) 😊

They'll announce the results in that discourse thread, so you can follow it to get notified right at the source.

just curious in some projects there is 0 % coverage . Will they be interested in improving this or there are any limitations ( which is stopping them ).

Some maintainers simply don't like Python typing (yet 😏 ), or prefer outsourcing it to typeshed or third party library

Comment thread docs/reference/index.md Outdated
- **[UFunc](numpy/ufunc.md)**: Universal functions
- **[Type Aliases](numpy/aliases.md)**: Common type aliases
- **[Low-level](numpy/low-level.md)**: Low-level NumPy interfaces
- **[ctypeslib](numpy/ctypeslib.md)**: Typed `ctypes` aliases for NumPy scalar-like C types

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's better, but it's a bit too long for a menu entry

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've updated with shorter version , let me know your thoughts

Comment thread docs/reference/index.md Outdated
Signed-off-by: Aniket <148300120+Aniketsy@users.noreply.github.com>

@jorenham jorenham left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had some time and gave this another look.

One general thing: The table markup is very long now; could you format it like in e.g. docs/reference/core/attributes.md?

Comment on lines +9 to +13
`optype.numpy.ctypeslib` re-exports standard-library `ctypes` constructors under
names that mirror NumPy's scalar naming — `Int32` for the `ctypes` counterpart of
`np.int32`, `LongDouble` for `np.longdouble`, and so on — and adds abstract type
aliases mirroring NumPy's scalar hierarchy (`SignedInteger`, `Inexact`,
`Generic`, …) for use in annotations.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this bit doens't really add much, and is alreayd explained below in fewer words

Comment on lines +78 to +81
Unlike NumPy, `ctypes` has no distinct fixed-width types. `c_int8` *is*
`c_byte`, `c_int16` *is* `c_short`, and the rest are resolved by `ctypes` at
import time from the platform's type sizes. A type checker cannot distinguish
names that resolve to the same class:

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't right, and also not really relevant here because we're just re-exporting types from ctypes

Comment on lines +83 to +95
<table>
<tr><th align="left">alias</th><th align="left"><code>ILP32</code></th><th align="left"><code>LP64</code></th><th align="left"><code>LLP64</code></th></tr>
<tr><td align="left"><code>Int8</code></td><td align="left"><code>Byte</code></td><td align="left"><code>Byte</code></td><td align="left"><code>Byte</code></td></tr>
<tr><td align="left"><code>UInt8</code></td><td align="left"><code>UByte</code></td><td align="left"><code>UByte</code></td><td align="left"><code>UByte</code></td></tr>
<tr><td align="left"><code>Int16</code></td><td align="left"><code>Short</code></td><td align="left"><code>Short</code></td><td align="left"><code>Short</code></td></tr>
<tr><td align="left"><code>UInt16</code></td><td align="left"><code>UShort</code></td><td align="left"><code>UShort</code></td><td align="left"><code>UShort</code></td></tr>
<tr><td align="left"><code>Int32</code></td><td align="left"><code>IntC</code> = <code>Long</code></td><td align="left"><code>IntC</code></td><td align="left"><code>IntC</code> = <code>Long</code></td></tr>
<tr><td align="left"><code>UInt32</code></td><td align="left"><code>UIntC</code> = <code>ULong</code></td><td align="left"><code>UIntC</code></td><td align="left"><code>UIntC</code> = <code>ULong</code></td></tr>
<tr><td align="left"><code>Int64</code></td><td align="left"><code>LongLong</code></td><td align="left"><code>Long</code> = <code>LongLong</code></td><td align="left"><code>LongLong</code></td></tr>
<tr><td align="left"><code>UInt64</code></td><td align="left"><code>ULongLong</code></td><td align="left"><code>ULong</code> = <code>ULongLong</code></td><td align="left"><code>ULongLong</code></td></tr>
<tr><td align="left"><code>IntP</code></td><td align="left"><code>IntC</code> = <code>Long</code></td><td align="left"><code>Long</code> = <code>LongLong</code></td><td align="left"><code>LongLong</code></td></tr>
<tr><td align="left"><code>UIntP</code></td><td align="left"><code>UIntC</code> = <code>ULong</code></td><td align="left"><code>ULong</code> = <code>ULongLong</code></td><td align="left"><code>ULongLong</code></td></tr>
</table>

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This suggests that the optype.numpy.ctypeslib types differ depending on the architecture, which isn't the case. So let's not make these docs a wiki on how types work in C, and linearly tabulate the exports.

Comment on lines +97 to +104
`ctypes` aliases `c_int` to `c_long` when the two have equal size, and
`c_longlong` to `c_long` likewise. So on `LP64`, `Long` **is** `LongLong`; on
`ILP32` and `LLP64`, `IntC` **is** `Long`. There is no data model on which all
three are distinct.

Annotating with either name of a pair is equally correct. The pairs exist so
code can be written in whichever vocabulary — NumPy's or C's — reads better at
the call site.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Following the same reasoning as above, this can go

Comment on lines +106 to +114
### `LongDouble`

`ctypes` collapses `c_longdouble` into `c_double` whenever the two have the same
size, so `LongDouble` *is* `Float64` on MSVC and on arm64 macOS.

`c_longdouble` also works only as a *type*, not as a value: its `.value` is a
Python `float`, i.e. a C `double`, so it cannot carry the extra precision of an
80- or 128-bit long double. Use it in `argtypes`/`restype` and in annotations;
don't use it to hold values.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is about C types, not about optype.numpy.ctypeslib

counterpart and are deliberately absent. `c_wchar` is likewise not exposed,
since NumPy maps no dtype onto it.

`Bytes` maps `np.bytes_` onto `c_char`, following

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no mapping; it's just a re-export under a different name

`np.long` and `np.ulong` are the NumPy 2.0 names for the C `long` types, and do
not exist under that spelling on `numpy < 2`.

### Types with no `ctypes` equivalent

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's call this something like "Differences between numpy and ctypes", because it also talks about differences between c_char and np.bytes_


`CType` and `CScalar` correspond to the private `ctypes` base classes that every
C type derives from. They exist at runtime, but neither is importable from
`ctypes` by name, and neither is meant to be instantiated — use them in

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's not use non-ascii characters like this emdash here

Comment on lines +184 to +197
### How the numeric aliases are defined

`Integer`, `Floating`, and `ComplexFloating` are not literally spelled as the
unions above. They are defined as `CScalar[int]`, `CScalar[float]`, and
`CScalar[complex]`, and `Inexact`/`Number` are built from those.

`ct._SimpleCData` is **invariant** in its type parameter, so `CScalar[int]`
resolves to exactly the C integer types listed above — and, unlike a literal
union, also admits any third-party `_SimpleCData[int]` subclass. The unions in
the table describe what these aliases match among the types in this module.

Invariance is also why `Bool` is listed separately in `Generic`: `c_bool` is a
`_SimpleCData[bool]`, and `bool` is not `int` under invariance, so `Bool` is not
covered by `Number`.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can seems like a lot of text to explain that "CScalar" is invariant; it's safe to assume that users know what invariance is, so let's skip the tutorial.

Comment on lines +199 to +227
## Example

```python
import ctypes as ct

import numpy as np
import optype.numpy.ctypeslib as opct

# the concrete names are the `ctypes` types themselves
assert opct.Int32 is ct.c_int32

buf = (opct.Int32 * 4)(1, 2, 3, 4)
arr = np.ctypeslib.as_array(buf)
assert arr.dtype == np.int32
```

`ctypes` converts simple return types to Python objects on call, so these names
belong on `argtypes`/`restype`, not on the Python-side return annotation:

```python
lib = ct.CDLL("libsum.so")

# int64_t sum_i32(const int32_t *values, int n)
lib.sum_i32.argtypes = [ct.POINTER(opct.Int32), opct.IntC]
lib.sum_i32.restype = opct.Int64


def zeroed[T: opct.Number](ctype: type[T], n: int) -> opct.Array[T]:
return (ctype * n)()

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These examples are more about ctypes than it is about numpy-related static typing. So let's just remove this and keep it focused.
Remember that these are reference docs, not a user guide.

@Aniketsy

Copy link
Copy Markdown
Contributor Author

I had some time and gave this another look.

Thanks for giving time and reviewing this

One general thing: The table markup is very long now; could you format it like in e.g. docs/reference/core/attributes.md?

make sense, i'll update 👍

@Aniketsy
Aniketsy marked this pull request as draft August 10, 2026 17:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Document optype.numpy.ctypes

3 participants