GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Enable ctypes by youknowone · Pull Request #6457 · RustPython/RustPython

Enable ctypes #6457

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.

Sign up for GitHub

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

Merged
youknowone merged 10 commits into RustPython:main from youknowone:ctypes
Dec 23, 2025

Uh oh!

There was an error while loading. Please reload this page.

Merged

Enable ctypes #6457

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
10 commits
Select commit Hold shift + click to select a range
9760249
fix multiarch
youknowone Dec 23, 2025
b44229f
debug whats_left
youknowone Dec 23, 2025
fc0a34a
Remove unused ctypes/field.rs
youknowone Dec 20, 2025
286a5b5
msc_info in get_version
youknowone Dec 23, 2025
4bf0bac
debuggable whats_left
youknowone Dec 23, 2025
79abbf0
fix ctypes
youknowone Dec 23, 2025
987216b
enable ctypes
youknowone Dec 16, 2025
03d6f46
Upgrade ctypes to Python v3.13.11
youknowone Dec 20, 2025
7e6e0f6
test_ctypes from CPython 3.13.11
youknowone Dec 20, 2025
4a35234
mark failing test_ctypes
youknowone Dec 20, 2025
File filter
Filter by extension

Clear filters
Conversations
Failed to load comments.
Loading

Uh oh!

There was an error while loading. Please reload this page.

Jump to
Jump to file
Failed to load files.
Loading

Uh oh!

There was an error while loading. Please reload this page.

Diff view
Diff view

There are no files selected for viewing

97 changes: 51 additions & 46 deletions 97 Lib/ctypes/__init__.py
Show comments
View file
Open in desktop
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
"""create and manipulate C data types in Python"""

import os as _os, sys as _sys
import os as _os
import sys as _sys
import sysconfig as _sysconfig
import types as _types

__version__ = "1.1.0"
Expand Down Expand Up @@ -36,9 +38,6 @@
FUNCFLAG_USE_ERRNO as _FUNCFLAG_USE_ERRNO, \
FUNCFLAG_USE_LASTERROR as _FUNCFLAG_USE_LASTERROR

# TODO: RUSTPYTHON remove this
from _ctypes import _non_existing_function

# WINOLEAPI -> HRESULT
# WINOLEAPI_(type)
#
Expand Down Expand Up @@ -110,7 +109,7 @@ class CFunctionType(_CFuncPtr):
return CFunctionType

if _os.name == "nt":
from _ctypes import LoadLibrary as _dlopen
from _ctypes import LoadLibrary as _LoadLibrary
from _ctypes import FUNCFLAG_STDCALL as _FUNCFLAG_STDCALL

_win_functype_cache = {}
Expand Down Expand Up @@ -305,8 +304,9 @@ def create_unicode_buffer(init, size=None):
raise TypeError(init)


# XXX Deprecated
def SetPointerType(pointer, cls):
import warnings
warnings._deprecated("ctypes.SetPointerType", remove=(3, 15))
if _pointer_type_cache.get(cls, None) is not None:
raise RuntimeError("This type already exists in the cache")
if id(pointer) not in _pointer_type_cache:
Expand All @@ -315,7 +315,6 @@ def SetPointerType(pointer, cls):
_pointer_type_cache[cls] = pointer
del _pointer_type_cache[id(pointer)]

# XXX Deprecated
def ARRAY(typ, len):
return typ * len

Expand Down Expand Up @@ -347,52 +346,59 @@ def __init__(self, name, mode=DEFAULT_MODE, handle=None,
use_errno=False,
use_last_error=False,
winmode=None):
class _FuncPtr(_CFuncPtr):
_flags_ = self._func_flags_
_restype_ = self._func_restype_
if use_errno:
_flags_ |= _FUNCFLAG_USE_ERRNO
if use_last_error:
_flags_ |= _FUNCFLAG_USE_LASTERROR

self._FuncPtr = _FuncPtr
if name:
name = _os.fspath(name)

self._handle = self._load_library(name, mode, handle, winmode)

if _os.name == "nt":
def _load_library(self, name, mode, handle, winmode):
if winmode is None:
import nt as _nt
winmode = _nt._LOAD_LIBRARY_SEARCH_DEFAULT_DIRS
# WINAPI LoadLibrary searches for a DLL if the given name
# is not fully qualified with an explicit drive. For POSIX
# compatibility, and because the DLL search path no longer
# contains the working directory, begin by fully resolving
# any name that contains a path separator.
if name is not None and ('/' in name or '\\' in name):
name = _nt._getfullpathname(name)
winmode |= _nt._LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR
self._name = name
if handle is not None:
return handle
return _LoadLibrary(self._name, winmode)

else:
def _load_library(self, name, mode, handle, winmode):
# If the filename that has been provided is an iOS/tvOS/watchOS
# .fwork file, dereference the location to the true origin of the
# binary.
if name.endswith(".fwork"):
if name and name.endswith(".fwork"):
with open(name) as f:
name = _os.path.join(
_os.path.dirname(_sys.executable),
f.read().strip()
)

self._name = name
flags = self._func_flags_
if use_errno:
flags |= _FUNCFLAG_USE_ERRNO
if use_last_error:
flags |= _FUNCFLAG_USE_LASTERROR
if _sys.platform.startswith("aix"):
"""When the name contains ".a(" and ends with ")",
e.g., "libFOO.a(libFOO.so)" - this is taken to be an
archive(member) syntax for dlopen(), and the mode is adjusted.
Otherwise, name is presented to dlopen() as a file argument.
"""
if name and name.endswith(")") and ".a(" in name:
mode |= ( _os.RTLD_MEMBER | _os.RTLD_NOW )
if _os.name == "nt":
if winmode is not None:
mode = winmode
else:
import nt
mode = nt._LOAD_LIBRARY_SEARCH_DEFAULT_DIRS
if '/' in name or '\\' in name:
self._name = nt._getfullpathname(self._name)
mode |= nt._LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR

class _FuncPtr(_CFuncPtr):
_flags_ = flags
_restype_ = self._func_restype_
self._FuncPtr = _FuncPtr

if handle is None:
self._handle = _dlopen(self._name, mode)
else:
self._handle = handle
if _sys.platform.startswith("aix"):
"""When the name contains ".a(" and ends with ")",
e.g., "libFOO.a(libFOO.so)" - this is taken to be an
archive(member) syntax for dlopen(), and the mode is adjusted.
Otherwise, name is presented to dlopen() as a file argument.
"""
if name and name.endswith(")") and ".a(" in name:
mode |= _os.RTLD_MEMBER | _os.RTLD_NOW
self._name = name
return _dlopen(name, mode)

def __repr__(self):
return "<%s '%s', handle %x at %#x>" % \
Expand Down Expand Up @@ -480,10 +486,9 @@ def LoadLibrary(self, name):

if _os.name == "nt":
pythonapi = PyDLL("python dll", None, _sys.dllhandle)
elif _sys.platform == "android":
pythonapi = PyDLL("libpython%d.%d.so" % _sys.version_info[:2])
elif _sys.platform == "cygwin":
pythonapi = PyDLL("libpython%d.%d.dll" % _sys.version_info[:2])
elif _sys.platform in ["android", "cygwin"]:
# These are Unix-like platforms which use a dynamically-linked libpython.
pythonapi = PyDLL(_sysconfig.get_config_var("LDLIBRARY"))
else:
pythonapi = PyDLL(None)

Expand Down
8 changes: 4 additions & 4 deletions 8 Lib/ctypes/_endian.py
Show comments
View file
Open in desktop
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import sys
from ctypes import *
from ctypes import Array, Structure, Union

_array_type = type(Array)

Expand All @@ -15,8 +15,8 @@ def _other_endian(typ):
# if typ is array
if isinstance(typ, _array_type):
return _other_endian(typ._type_) * typ._length_
# if typ is structure
if issubclass(typ, Structure):
# if typ is structure or union
if issubclass(typ, (Structure, Union)):
return typ
raise TypeError("This type does not support other endian: %s" % typ)

Expand All @@ -37,7 +37,7 @@ class _swapped_union_meta(_swapped_meta, type(Union)): pass
################################################################

# Note: The Structure metaclass checks for the *presence* (not the
# value!) of a _swapped_bytes_ attribute to determine the bit order in
# value!) of a _swappedbytes_ attribute to determine the bit order in
# structures containing bit fields.

if sys.byteorder == "little":
Expand Down
16 changes: 0 additions & 16 deletions 16 Lib/ctypes/test/__init__.py
Show comments
View file
Open in desktop

This file was deleted.

Oops, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

4 changes: 0 additions & 4 deletions 4 Lib/ctypes/test/__main__.py
Show comments
View file
Open in desktop

This file was deleted.

Oops, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

21 changes: 0 additions & 21 deletions 21 Lib/ctypes/test/test_delattr.py
Show comments
View file
Open in desktop

This file was deleted.

Oops, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

55 changes: 0 additions & 55 deletions 55 Lib/ctypes/test/test_simplesubclasses.py
Show comments
View file
Open in desktop

This file was deleted.

Oops, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

18 changes: 15 additions & 3 deletions 18 Lib/ctypes/util.py
Show comments
View file
Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ def find_library(name):
return fname
return None

elif os.name == "posix" and sys.platform == "darwin":
elif os.name == "posix" and sys.platform in {"darwin", "ios", "tvos", "watchos"}:
from ctypes.macholib.dyld import dyld_find as _dyld_find
def find_library(name):
possible = ['lib%s.dylib' % name,
Expand All @@ -89,15 +89,27 @@ def find_library(name):

from ctypes._aix import find_library

elif sys.platform == "android":
def find_library(name):
directory = "/system/lib"
if "64" in os.uname().machine:
directory += "64"

fname = f"{directory}/lib{name}.so"
return fname if os.path.isfile(fname) else None

elif os.name == "posix":
# Andreas Degert's find functions, using gcc, /sbin/ldconfig, objdump
import re, tempfile

def _is_elf(filename):
"Return True if the given file is an ELF file"
elf_header = b'\x7fELF'
with open(filename, 'br') as thefile:
return thefile.read(4) == elf_header
try:
with open(filename, 'br') as thefile:
return thefile.read(4) == elf_header
except FileNotFoundError:
return False

def _findLib_gcc(name):
# Run GCC's linker with the -t (aka --trace) option and examine the
Expand Down
2 changes: 1 addition & 1 deletion 2 Lib/platform.py
Show comments
View file
Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -1080,7 +1080,7 @@ def _sys_version(sys_version=None):
match.groups()

# XXX: RUSTPYTHON support
if "rustc" in sys_version:
if "RustPython" in sys_version:
name = "RustPython"
else:
name = 'CPython'
Expand Down
10 changes: 0 additions & 10 deletions 10 Lib/test/test_ctypes.py
Show comments
View file
Open in desktop

This file was deleted.

Oops, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

10 changes: 10 additions & 0 deletions 10 Lib/test/test_ctypes/__init__.py
Show comments
View file
Open in desktop
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import os
from test import support
from test.support import import_helper


# skip tests if the _ctypes extension was not built
import_helper.import_module('ctypes')

def load_tests(*args):
return support.load_package_tests(os.path.dirname(__file__), *args)
4 changes: 4 additions & 0 deletions 4 Lib/test/test_ctypes/__main__.py
Show comments
View file
Open in desktop
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from test.test_ctypes import load_tests
import unittest

unittest.main()
24 changes: 24 additions & 0 deletions 24 Lib/test/test_ctypes/_support.py
Show comments
View file
Open in desktop
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Some classes and types are not export to _ctypes module directly.

import ctypes
from _ctypes import Structure, Union, _Pointer, Array, _SimpleCData, CFuncPtr


_CData = Structure.__base__
assert _CData.__name__ == "_CData"

class _X(Structure):
_fields_ = [("x", ctypes.c_int)]
CField = type(_X.x)

# metaclasses
PyCStructType = type(Structure)
UnionType = type(Union)
PyCPointerType = type(_Pointer)
PyCArrayType = type(Array)
PyCSimpleType = type(_SimpleCData)
PyCFuncPtrType = type(CFuncPtr)

# type flags
Py_TPFLAGS_DISALLOW_INSTANTIATION = 1 << 7
Py_TPFLAGS_IMMUTABLETYPE = 1 << 8
Loading
Oops, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

Loading
Oops, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

Add this suggestion to a batch that can be applied as a single commit. This suggestion is invalid because no changes were made to the code. Suggestions cannot be applied while the pull request is closed. Suggestions cannot be applied while viewing a subset of changes. Only one suggestion per line can be applied in a batch. Add this suggestion to a batch that can be applied as a single commit. Applying suggestions on deleted lines is not supported. You must change the existing code in this line in order to create a valid suggestion. Outdated suggestions cannot be applied. This suggestion has been applied or marked resolved. Suggestions cannot be applied from pending reviews. Suggestions cannot be applied on multi-line comments. Suggestions cannot be applied while the pull request is queued to merge. Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.