8000 Add support for C99 complex type (_Complex) as ctypes.c_complex · Issue #61103 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

Add support for C99 complex type (_Complex) as ctypes.c_complex #61103

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
rutsky mannequin opened this issue Jan 8, 2013 · 28 comments · Fixed by #121248
Closed

Add support for C99 complex type (_Complex) as ctypes.c_complex #61103

rutsky mannequin opened this issue Jan 8, 2013 · 28 comments · Fixed by #121248
Labels
topic-ctypes type-feature A feature request or enhancement

Comments

@rutsky
Copy link
Mannequin
rutsky mannequin commented Jan 8, 2013
BPO 16899
Nosy @arigo, @amauryfa, @mdickinson, @meadori

Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

Show more details

GitHub fields:

assignee = None
closed_at = None
created_at = <Date 2013-01-08.22:06:03.435>
labels = ['ctypes', 'type-feature', '3.7']
title = 'Add support for C99 complex type (_Complex) as ctypes.c_complex'
updated_at = <Date 2018-07-04.15:01:25.648>
user = 'https://bugs.python.org/rutsky'

bugs.python.org fields:

activity = <Date 2018-07-04.15:01:25.648>
actor = 'arigo'
assignee = 'none'
closed = False
closed_date = None
closer = None
components = ['ctypes']
creation = <Date 2013-01-08.22:06:03.435>
creator = 'rutsky'
dependencies = []
files = []
hgrepos = []
issue_num = 16899
keywords = []
message_count = 10.0
messages = ['179378', '179459', '179609', '179646', '180759', '285961', '285998', '286453', '321046', '321049']
nosy_count = 8.0
nosy_names = ['arigo', 'amaury.forgeotdarc', 'mark.dickinson', 'Arfrever', 'meador.inge', 'rutsky', 'Tom Krauss', 'rkmountainguy']
pr_nums = []
priority = 'normal'
resolution = None
stage = 'test needed'
status = 'open'
superseder = None
type = 'enhancement'
url = 'https://bugs.python.org/issue16899'
versions = ['Python 3.7']

Linked PRs

@rutsky
Copy link
Mannequin Author
rutsky mannequin commented Jan 8, 2013

It would be nice if Python will be able to access variables with C99 complex types through ctypes module.

@rutsky rutsky mannequin added topic-ctypes type-feature A feature request or enhancement labels Jan 8, 2013
@amauryfa
Copy link
Contributor
amauryfa commented Jan 9, 2013

libffi still has no support for _Complex.

Did you try with a pure Python solution, like the one suggested in http://objectmix.com/python/112374-re-ctypes-c99-complex-numbers.html

@rutsky
Copy link
Mannequin Author
rutsky mannequin commented Jan 11, 2013

Yes, I managed to pass and operate with matrices of complex numbers to pure C and Fortran programs by using Numpy and their ctype adapters (only for whole matrices, they don't provide c_complex type; in general see http://www.scipy.org/Cookbook/Ctypes for details).

I suppose pure python solution that suggested in provided by you link works too:

class Complex64(Structure):
    _fields_ = [("real", c_float), ("imag", c_float)]

But I'm unsure is this is expected behavior or luck, and on some platform this code will not work due to different complex numbers internal representation.

Any way this should be implemented in libffi first, and then in ctypes, so this feature request should be postponed, IMO.

@mdickinson
Copy link
Member

But I'm unsure is this is expected behavior or luck, and on some
platform this code will not work due to different complex numbers
internal representation.

What platform? Isn't the complex number representation standard? E.g., C99 6.2.5p13 says: "Each complex type has the same representation and alignment requirements as an array type containing exactly two elements of the corresponding real type; the first element is equal to the real part, and the second element to the imaginary part, of the complex number."

@mdickinson
Copy link
Member

Postponing as suggested.

@TomKrauss
Copy link
Mannequin
TomKrauss mannequin commented Jan 21, 2017

I'm trying to add support for this in cffi, which uses ctypes... apparently this is now supported in libffi (https://github.com/libffi/libffi, v3.2 Nov 2014).
It would be nice if this issue could be re-opened, or another one created for the same purpose.

@mdickinson
Copy link
Member

Thanks, Tom. Re-opening.

@mdickinson mdickinson reopened this Jan 22, 2017
@arigo
Copy link
Mannequin
arigo mannequin commented Jan 29, 2017
  • Tom: the issue is unrelated to cffi, but both ctypes and cffi could proceed to support C complexes, now that libffi support has been added.

  • Mark: the problem is that the text you quote from the C standard fixes the representation of a complex in memory, but doesn't say anything about directly passing a complex as argument or return value to a function call. Platforms use custom ways to do that. The text you quote says a complex is an array of two real numbers; but passing an array as argument to a function works by passing a pointer to the first element. Typically, this is not how complexes are passed: instead, some pointerless form of "passing two real numbers" is used.

@rkmountainguy
Copy link
Mannequin
rkmountainguy mannequin commented Jul 4, 2018

I concur with rutsky. Complex numbers are essential in the physical sciences, and the complex type is part of the c99 standard. Trying to shoehorn complex support by a user-defined type makes use of 8000 the builtin methods for the standard complex type clunky.

@rkmountainguy rkmountainguy mannequin added the 3.7 (EOL) end of life label Jul 4, 2018
@arigo
Copy link
Mannequin
arigo mannequin commented Jul 4, 2018

cffi supports complex numbers since release 1.11---for direct calls using the API mode. That means that neither CFFI's ABI mode, nor ctypes, can possibly work yet. The problem is still libffi's own support, which is still not implemented (apart on a very uncommon CPU architecture, the s390).

@ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
@skirpichev
Copy link
Member

Pure python approach works for me so far (recent gcc/clang with glibc):

>>> import ctypes
>>> libm = ctypes.CDLL('libm.so.6')
>>> class c_complex(ctypes.Structure):
...     _fields_ = [("real", ctypes.c_double),
...                 ("imag", ctypes.c_double)]
...     @property
...     def value(self):
...         return complex(self.real, self.imag)
...
>>> libm.clog.argtypes = [c_complex]
>>> libm.clog.restype = c_complex
>>> libm.clog(c_complex(1, 1)).value
(0.34657359027997264+0.7853981633974483j)

But I'm working on adding primitive data types for C complexes in the ctypes. Naming: c_float_complex, c_double_complex (or just c_complex?) and c_longdouble_complex.

@picnixz
Copy link
Member
picnixz commented Jun 22, 2024

My 2 cents: I'd go for c_double_complex instead of c_complex because it's the name used in Fortran (and it could be useful to have mapping names like that). In addition, since we use c_float_complex, using c_double_complex really stresses that we are using a double _Complex. Also, while GCC/clang assumes _Complex to be double _Complex, they raise a warning (assuming -Wpedantic and -Wsystem-headers for GCC).

skirpichev added a commit to skirpichev/cpython that referenced this issue Jun 23, 2024
Example:
```pycon
>>> import ctypes
>>> ctypes.__STDC_IEC_559_COMPLEX__
1
>>> libm = ctypes.CDLL('libm.so.6')
>>> libm.clog.argtypes = [ctypes.c_double_complex]
>>> libm.clog.restype = ctypes.c_double_complex
>>> libm.clog(1+1j)
(0.34657359027997264+0.7853981633974483j)
```

``ctypes.__STDC_IEC_559_COMPLEX__`` is ``0`` if compiler doesn't support
complex arithmetic (Annex G).
@skirpichev
Copy link
Member

PR ready for review: #120894

vstinner added a commit that referenced this issue Jul 1, 2024
Example:

```pycon
>>> import ctypes
>>> ctypes.__STDC_IEC_559_COMPLEX__
1
>>> libm = ctypes.CDLL('libm.so.6')
>>> libm.clog.argtypes = [ctypes.c_double_complex]
>>> libm.clog.restype = ctypes.c_double_complex
>>> libm.clog(1+1j)
(0.34657359027997264+0.7853981633974483j)
```

Co-authored-by: Nice Zombies <nineteendo19d0@gmail.com>
Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
Co-authored-by: Victor Stinner <vstinner@python.org>
@vstinner
Copy link
Member
vstinner commented Jul 1, 2024

Implemented by change 6988ff0.

@vstinner vstinner closed this as completed Jul 1, 2024
@skirpichev
Copy link
Member
skirpichev commented Jul 1, 2024

Hmm, @vstinner, should this be closed? At least support for double _Complex was added, but there are float _Complex and long double _Complex, C standards specify three types. Adding these should be more or less mechanical, but maybe we should reconsider 1-char names for new types (see #120894 (comment)).

Also, the struct module can include an interface to _Complex (that part was removed from pr).

@vstinner
Copy link
Member
vstinner commented Jul 1, 2024

I would prefer to only support double _Complex for now. I'm not sure that float and long double are popular enough.

@skirpichev
Copy link
Member

I'm not sure that is about popularity. It's not why there are float and long double types, not just double.

@vstinner
Copy link
Member
vstinner commented Jul 1, 2024

It's up to you. I reopen the issue.

@encukou
Copy link
Member
encukou commented Jan 21, 2025

I think this needs a What's New entry: #129129

encukou added a commit that referenced this issue Jan 22, 2025
Co-authored-by: Sergey B Kirpichev <skirpichev@gmail.com>
@vstinner
Copy link
Member

I think this needs a What's New entry: #129129

@skirpichev: Can you document the new features in What's New in Python 3.14?

@skirpichev
Copy link
Member

@vstinner, did I miss something? I thought this was done in the Petr's pr.

@vstinner
Copy link
Member

Oh nevermind, I missed Petr's PR!

@skirpichev
Copy link
Member

Now I think that @dalcinl was right and we shouldn't require Annex G support from compiler, when CPython is built.

As a first step, we could avoid using Annex G types (i.e. replace them with appropriate 2-elements arrays) in helpers (like D_get/set()), as C standard provides some guaranties on memory layout for complex types.

@skirpichev skirpichev reopened this May 1, 2025
skirpichev added a commit to skirpichev/cpython that referenced this issue May 1, 2025
…ctypes

* drop _complex.h header
* use appropriate real arrays to replace complex types
skirpichev added a commit to skirpichev/cpython that referenced this issue May 1, 2025
…ctypes

* drop _complex.h header
* use appropriate real arrays to replace complex types
encukou added a commit that referenced this issue May 5, 2025
…-133237)

According to the C standard, the memory representation of _Complex types
is equivalent to 2-element arrays. Unlike _Complex, arrays are always available.

- drop _complex.h header
- use appropriate real arrays to replace complex types

Co-authored-by: Lisandro Dalcin <dalcinl@gmail.com>
Co-authored-by: Petr Viktorin <encukou@gmail.com>
Co-authored-by: Stan Ulbrych <89152624+StanFromIreland@users.noreply.github.com>
@encukou
Copy link
Member
encukou commented May 5, 2025

@skirpichev said in the now-merged #133237:

Note, that Py_FFI_SUPPORT_C_COMPLEX check configure check imply support for complex types. So, Py_HAVE_C_COMPLEX check is redundant. Though, I'm not sure if it worth removing.

Py_HAVE_C_COMPLEX technically part of the public API namespace, so you could say PEP 387 applies to it. IMO, properly deprecating a #define-ition is too onerous to be worth it.

I'd welcome tests that compare Python's complex numbers to the compiler's Annex G implementation (if any), so the macro might still be useful for _testcapi.

@skirpichev
Copy link
Member

Py_HAVE_C_COMPLEX technically part of the public API namespace

It was introduced in 3.14, thus backward compatibility is not a problem.

so the macro might still be useful for _testcapi.

Lets keep it for a while.

@encukou
Copy link
Member
encukou commented May 5, 2025

It was introduced in 3.14

Ah, rigth! In that case, let's remove it (some time during the beta period).
It can be reintroduced as _Py_HAVE_C_COMPLEX.

@encukou encukou reopened this May 5, 2025
skirpichev added a commit to skirpichev/cpython that referenced this issue May 5, 2025
The Py_FFI_SUPPORT_C_COMPLEX check configure check imply support for
complex types.
skirpichev added a commit to skirpichev/cpython that referenced this issue May 5, 2025
The Py_FFI_SUPPORT_C_COMPLEX check configure check imply support for
complex types.
encukou pushed a commit that referenced this issue May 5, 2025
Py_HAVE_C_COMPLEX was added in 3.14 so the removal doesn't need a deprecation
period even under a strict reading of PEP 387.

The Py_FFI_SUPPORT_C_COMPLEX check configure check implies support for
complex types in ctypes.
@encukou
Copy link
Member
encukou commented May 5, 2025

Thank you!

@encukou encukou closed this as completed May 5, 2025
@skirpichev skirpichev removed their assignment May 7, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
topic-ctypes type-feature A feature request or enhancement
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants
0