[clang] [libclang/python] Derive library function types from annotations (PR #142120)
Jannick Kremer via cfe-commits
cfe-commits at lists.llvm.org
Fri Jun 6 23:54:56 PDT 2025
DeinAlptraum wrote:
@Endilll I think I might not have been clear, the issue I am the most concerned about is the following.
As an example, consider `clang_PrintingPolicy_getProperty`. Previously, it was defined in `FUNCTION_LIST` as
```python
("clang_PrintingPolicy_getProperty", [PrintingPolicy, c_int], c_uint),
```
and correspondingly, its signature in the `ClangLib` protocol in this PR is
```python
def clang_PrintingPolicy_getProperty(self, arg1: PrintingPolicy, arg2: c_int) -> c_uint: ...
```
Then the `_get_annotations` function can extract the argument and return types to correctly register the C function on the library object, with these `c_int`, `c_uint` types. The problem is, `ctypes` adds automatic conversion here _once the function is registered_. So after the registration, the second argument expects a Python `int`, and it also returns a Python `int`. So our interface would have to be correctly annotated as
```python
def get_property(self, property: PrintingPolicyProperty) -> int:
"""Get a property value for the given printing policy."""
return conf.lib.clang_PrintingPolicy_getProperty(self, property.value)
```
but that leads to the following type errors:
```
clang/cindex.py:3980: error: Incompatible return value type (got "c_uint", expected "int") [return-value]
clang/cindex.py:3980: error: Argument 2 to "clang_PrintingPolicy_getProperty" of "ClangLib" has incompatible type "int"; expected "c_int" [arg-type]
```
I.e. the library function automatically converts Python `int` to `c_int` when they are passed, and the `c_uint` to a Python `int` on return. This is why our interface implementation also passes a Python `int` (`property.value`) into the function and can return a Python `int` without having to call any conversion functions. The above annotation of the interface is thus correct, but due to the automatic conversion, the previous annotation on the `ClangLib` protocol are now incorrect, leading to the type-checker errors (the code itself runs perfectly fine).
Unfortunately, I don't see a way around this: we need to register the functions on the library object by explicitly giving it the corresponding `ctypes` types, and we need to annotate the `ClangLib` protocol with the Python types in order for type-checking to get reasonable results. As we want to derive the library function types from the annotations, we need a map from Python types to `ctypes` types, but this is not possible due to the ambiguity e.g. Python `int` maps to both `c_int` and `c_uint`.
https://github.com/llvm/llvm-project/pull/142120
More information about the cfe-commits
mailing list