ctypes — Eine Fremdfunktionsbibliothek für Python¶
Quellcode: Lib/ctypes
ctypes ist eine Fremdfunktionsbibliothek für Python. Sie stellt C-kompatible Datentypen bereit und ermöglicht das Aufrufen von Funktionen in DLLs oder Shared Libraries. Sie kann verwendet werden, um diese Bibliotheken in reinem Python einzubinden.
ctypes Tutorial¶
Hinweis: Die Codebeispiele in diesem Tutorial verwenden doctest, um sicherzustellen, dass sie tatsächlich funktionieren. Da einige Codebeispiele unter Linux, Windows oder macOS unterschiedlich verhalten, enthalten sie doctest-Direktiven in Kommentaren.
Hinweis: Einige Codebeispiele beziehen sich auf den c_int Typ von ctypes. Auf Plattformen, auf denen sizeof(long) == sizeof(int) ist, ist er ein Alias für c_long. Daher sollten Sie nicht verwirrt sein, wenn c_long ausgegeben wird, wenn Sie c_int erwarten – es handelt sich tatsächlich um denselben Typ.
Laden von dynamischen Linkbibliotheken¶
ctypes exportiert die Objekte cdll und unter Windows windll und oledll zum Laden von dynamischen Linkbibliotheken.
Sie laden Bibliotheken, indem Sie auf sie als Attribute dieser Objekte zugreifen. cdll lädt Bibliotheken, die Funktionen mit der Standard-Aufrufkonvention cdecl exportieren, während windll-Bibliotheken Funktionen mit der Aufrufkonvention stdcall aufrufen. oledll verwendet ebenfalls die Aufrufkonvention stdcall und geht davon aus, dass die Funktionen einen Windows HRESULT-Fehlercode zurückgeben. Der Fehlercode wird verwendet, um automatisch eine OSError-Ausnahme auszulösen, wenn der Funktionsaufruf fehlschlägt.
Geändert in Version 3.3: Windows-Fehler lösten früher WindowsError aus, was jetzt ein Alias für OSError ist.
Hier sind einige Beispiele für Windows. Beachten Sie, dass msvcrt die standardmäßige C-Bibliothek von MS ist, die die meisten Standard-C-Funktionen enthält, und die Aufrufkonvention cdecl verwendet.
>>> from ctypes import *
>>> print(windll.kernel32)
<WinDLL 'kernel32', handle ... at ...>
>>> print(cdll.msvcrt)
<CDLL 'msvcrt', handle ... at ...>
>>> libc = cdll.msvcrt
>>>
Windows hängt die übliche Dateiendung .dll automatisch an.
Hinweis
Der Zugriff auf die Standard-C-Bibliothek über cdll.msvcrt verwendet eine veraltete Version der Bibliothek, die möglicherweise nicht mit der von Python verwendeten kompatibel ist. Wenn möglich, verwenden Sie native Python-Funktionalitäten oder importieren und verwenden Sie das Modul msvcrt.
Unter Linux ist es erforderlich, den Dateinamen *einschließlich* der Erweiterung anzugeben, um eine Bibliothek zu laden. Daher kann der Attributzugriff nicht zum Laden von Bibliotheken verwendet werden. Entweder sollte die Methode LoadLibrary() der DLL-Loader verwendet werden, oder Sie sollten die Bibliothek laden, indem Sie eine Instanz von CDLL durch Aufrufen des Konstruktors erstellen.
>>> cdll.LoadLibrary("libc.so.6")
<CDLL 'libc.so.6', handle ... at ...>
>>> libc = CDLL("libc.so.6")
>>> libc
<CDLL 'libc.so.6', handle ... at ...>
>>>
Zugriff auf Funktionen aus geladenen DLLs¶
Funktionen werden als Attribute von DLL-Objekten abgerufen.
>>> libc.printf
<_FuncPtr object at 0x...>
>>> print(windll.kernel32.GetModuleHandleA)
<_FuncPtr object at 0x...>
>>> print(windll.kernel32.MyOwnFunction)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "ctypes.py", line 239, in __getattr__
func = _StdcallFuncPtr(name, self)
AttributeError: function 'MyOwnFunction' not found
>>>
Beachten Sie, dass win32-System-DLLs wie kernel32 und user32 oft sowohl ANSI- als auch UNICODE-Versionen einer Funktion exportieren. Die UNICODE-Version wird mit einem angehängten W benannt, während die ANSI-Version mit einem angehängten A benannt wird. Die win32-Funktion GetModuleHandle, die ein *Modulhandle* für einen gegebenen Modulnamen zurückgibt, hat den folgenden C-Prototyp, und ein Makro wird verwendet, um eine davon als GetModuleHandle verfügbar zu machen, je nachdem, ob UNICODE definiert ist oder nicht.
/* ANSI version */
HMODULE GetModuleHandleA(LPCSTR lpModuleName);
/* UNICODE version */
HMODULE GetModuleHandleW(LPCWSTR lpModuleName);
windll versucht nicht, eine davon magisch auszuwählen; Sie müssen auf die benötigte Version zugreifen, indem Sie explizit GetModuleHandleA oder GetModuleHandleW angeben und sie dann mit Byte- oder Zeichenkettenobjekten bzw. aufrufen.
Manchmal exportieren DLLs Funktionen mit Namen, die keine gültigen Python-Bezeichner sind, wie z. B. "??2@YAPAXI@Z". In diesem Fall müssen Sie getattr() verwenden, um die Funktion abzurufen.
>>> getattr(cdll.msvcrt, "??2@YAPAXI@Z")
<_FuncPtr object at 0x...>
>>>
Unter Windows exportieren einige DLLs Funktionen nicht nach Namen, sondern nach Ordinalzahl. Diese Funktionen können durch Indizierung des DLL-Objekts mit der Ordinalzahl abgerufen werden.
>>> cdll.kernel32[1]
<_FuncPtr object at 0x...>
>>> cdll.kernel32[0]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "ctypes.py", line 310, in __getitem__
func = _StdcallFuncPtr(name, self)
AttributeError: function ordinal 0 not found
>>>
Aufrufen von Funktionen¶
Sie können diese Funktionen wie jede andere Python-Funktion aufrufen. Dieses Beispiel verwendet die Funktion rand(), die keine Argumente nimmt und eine Pseudozufallszahl zurückgibt.
>>> print(libc.rand())
1804289383
Unter Windows können Sie die Funktion GetModuleHandleA() aufrufen, die ein win32-Modulhandle zurückgibt (wobei None als einziges Argument übergeben wird, um sie mit einem NULL-Zeiger aufzurufen).
>>> print(hex(windll.kernel32.GetModuleHandleA(None)))
0x1d000000
>>>
ValueError wird ausgelöst, wenn Sie eine stdcall-Funktion mit der cdecl-Aufrufkonvention oder umgekehrt aufrufen.
>>> cdll.kernel32.GetModuleHandleA(None)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: Procedure probably called with not enough arguments (4 bytes missing)
>>>
>>> windll.msvcrt.printf(b"spam")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: Procedure probably called with too many arguments (4 bytes in excess)
>>>
Um die korrekte Aufrufkonvention herauszufinden, müssen Sie die C-Headerdatei oder die Dokumentation der aufzurufenden Funktion konsultieren.
Unter Windows verwendet ctypes die win32-Strukturierte Ausnahmebehandlung, um Abstürze durch allgemeine Schutzfehler zu verhindern, wenn Funktionen mit ungültigen Argumentwerten aufgerufen werden.
>>> windll.kernel32.GetModuleHandleA(32)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OSError: exception: access violation reading 0x00000020
>>>
Es gibt jedoch genügend Möglichkeiten, Python mit ctypes zum Absturz zu bringen, sodass Sie trotzdem vorsichtig sein sollten. Das Modul faulthandler kann bei der Fehlersuche (z. B. bei Segmentierungsfehlern, die durch fehlerhafte C-Bibliotheksaufrufe verursacht werden) hilfreich sein.
None, Ganzzahlen, Bytes-Objekte und (Unicode-)Strings sind die einzigen nativen Python-Objekte, die direkt als Parameter in diesen Funktionsaufrufen verwendet werden können. None wird als C NULL-Zeiger übergeben, Bytes-Objekte und Strings werden als Zeiger auf den Speicherblock übergeben, der ihre Daten enthält (char* oder wchar_t*). Python-Ganzzahlen werden als Standard-C-int-Typ der Plattform übergeben, ihr Wert wird maskiert, um in den C-Typ zu passen.
Bevor wir uns dem Aufrufen von Funktionen mit anderen Parametertypen zuwenden, müssen wir mehr über die Datentypen von ctypes erfahren.
Grundlegende Datentypen¶
ctypes definiert eine Reihe von primitiven C-kompatiblen Datentypen.
ctypes-Typ |
C-Typ |
Python Typ |
|---|---|---|
_Bool |
bool (1) |
|
char |
1-Zeichen Bytes-Objekt |
|
|
1-Zeichen String |
|
char |
int |
|
unsigned char |
int |
|
short |
int |
|
unsigned short |
int |
|
int |
int |
|
|
int |
|
|
int |
|
|
int |
|
|
int |
|
unsigned int |
int |
|
|
int |
|
|
int |
|
|
int |
|
|
int |
|
long |
int |
|
unsigned long |
int |
|
__int64 oder long long |
int |
|
unsigned __int64 oder unsigned long long |
int |
|
|
int |
|
|
int |
|
|
int |
|
float |
float |
|
double |
float |
|
long double |
float |
|
char* (NUL-terminiert) |
Bytes-Objekt oder |
|
wchar_t* (NUL-terminiert) |
String oder |
|
void* |
Ganzzahl oder |
Der Konstruktor akzeptiert jedes Objekt mit einem Wahrheitswert.
Zusätzlich, wenn IEC 60559-kompatible komplexe Arithmetik (Anhang G) sowohl in C als auch in libffi unterstützt wird, sind die folgenden komplexen Typen verfügbar:
ctypes-Typ |
C-Typ |
Python Typ |
|---|---|---|
float complex |
komplex |
|
double complex |
komplex |
|
long double complex |
komplex |
Alle diese Typen können durch Aufruf mit einem optionalen Initialisierer des richtigen Typs und Werts erstellt werden.
>>> c_int()
c_long(0)
>>> c_wchar_p("Hello, World")
c_wchar_p(140018365411392)
>>> c_ushort(-3)
c_ushort(65533)
>>>
Da diese Typen veränderlich sind, kann ihr Wert auch nachträglich geändert werden.
>>> i = c_int(42)
>>> print(i)
c_long(42)
>>> print(i.value)
42
>>> i.value = -99
>>> print(i.value)
-99
>>>
Das Zuweisen eines neuen Werts zu Instanzen der Zeigertypen c_char_p, c_wchar_p und c_void_p ändert den *Speicherort*, auf den sie zeigen, *nicht den Inhalt* des Speicherblocks (natürlich nicht, da Python-String-Objekte unveränderlich sind).
>>> s = "Hello, World"
>>> c_s = c_wchar_p(s)
>>> print(c_s)
c_wchar_p(139966785747344)
>>> print(c_s.value)
Hello World
>>> c_s.value = "Hi, there"
>>> print(c_s) # the memory location has changed
c_wchar_p(139966783348904)
>>> print(c_s.value)
Hi, there
>>> print(s) # first object is unchanged
Hello, World
>>>
Sie sollten jedoch vorsichtig sein, diese nicht an Funktionen zu übergeben, die Zeiger auf veränderlichen Speicher erwarten. Wenn Sie veränderliche Speicherblöcke benötigen, verfügt ctypes über eine Funktion create_string_buffer(), die diese auf verschiedene Arten erstellt. Der aktuelle Inhalt des Speicherblocks kann über die Eigenschaft raw abgerufen (oder geändert) werden; wenn Sie darauf als NUL-terminierten String zugreifen möchten, verwenden Sie die Eigenschaft value.
>>> from ctypes import *
>>> p = create_string_buffer(3) # create a 3 byte buffer, initialized to NUL bytes
>>> print(sizeof(p), repr(p.raw))
3 b'\x00\x00\x00'
>>> p = create_string_buffer(b"Hello") # create a buffer containing a NUL terminated string
>>> print(sizeof(p), repr(p.raw))
6 b'Hello\x00'
>>> print(repr(p.value))
b'Hello'
>>> p = create_string_buffer(b"Hello", 10) # create a 10 byte buffer
>>> print(sizeof(p), repr(p.raw))
10 b'Hello\x00\x00\x00\x00\x00'
>>> p.value = b"Hi"
>>> print(sizeof(p), repr(p.raw))
10 b'Hi\x00lo\x00\x00\x00\x00\x00'
>>>
Die Funktion create_string_buffer() ersetzt die alte Funktion c_buffer() (die noch als Alias verfügbar ist). Um einen veränderlichen Speicherblock zu erstellen, der Unicode-Zeichen vom C-Typ wchar_t enthält, verwenden Sie die Funktion create_unicode_buffer().
Aufrufen von Funktionen, Fortsetzung¶
Beachten Sie, dass printf auf den tatsächlichen Standardausgabekanal schreibt, *nicht* auf sys.stdout. Diese Beispiele funktionieren daher nur an der Konsolenaufforderung, nicht innerhalb von *IDLE* oder *PythonWin*.
>>> printf = libc.printf
>>> printf(b"Hello, %s\n", b"World!")
Hello, World!
14
>>> printf(b"Hello, %S\n", "World!")
Hello, World!
14
>>> printf(b"%d bottles of beer\n", 42)
42 bottles of beer
19
>>> printf(b"%f bottles of beer\n", 42.5)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ctypes.ArgumentError: argument 2: TypeError: Don't know how to convert parameter 2
>>>
Wie bereits erwähnt, müssen alle Python-Typen außer Ganzzahlen, Strings und Bytes-Objekten in ihren entsprechenden ctypes-Typen eingepackt werden, damit sie in den erforderlichen C-Datentyp konvertiert werden können.
>>> printf(b"An int %d, a double %f\n", 1234, c_double(3.14))
An int 1234, a double 3.140000
31
>>>
Aufrufen von variadischen Funktionen¶
Auf vielen Plattformen ist das Aufrufen variadischer Funktionen über ctypes genau dasselbe wie das Aufrufen von Funktionen mit einer festen Anzahl von Parametern. Auf einigen Plattformen, insbesondere ARM64 für Apple Platforms, ist die Aufrufkonvention für variadische Funktionen anders als für reguläre Funktionen.
Auf diesen Plattformen ist es erforderlich, das Attribut argtypes für die regulären, nicht-variadischen Funktionsargumente anzugeben.
libc.printf.argtypes = [ctypes.c_char_p]
Da die Angabe des Attributs die Portabilität nicht beeinträchtigt, wird empfohlen, argtypes immer für alle variadischen Funktionen anzugeben.
Aufrufen von Funktionen mit eigenen benutzerdefinierten Datentypen¶
Sie können auch die Argumentkonvertierung von ctypes anpassen, um Instanzen Ihrer eigenen Klassen als Funktionsargumente zu verwenden. ctypes sucht nach einem Attribut _as_parameter_ und verwendet dieses als Funktionsargument. Das Attribut muss eine Ganzzahl, ein String, Bytes, eine ctypes-Instanz oder ein Objekt mit einem Attribut _as_parameter_ sein.
>>> class Bottles:
... def __init__(self, number):
... self._as_parameter_ = number
...
>>> bottles = Bottles(42)
>>> printf(b"%d bottles of beer\n", bottles)
42 bottles of beer
19
>>>
Wenn Sie die Daten der Instanz nicht in der Instanzvariable _as_parameter_ speichern möchten, könnten Sie eine property definieren, die das Attribut bei Bedarf verfügbar macht.
Angabe der erforderlichen Argumenttypen (Funktionsprototypen)¶
Es ist möglich, die erforderlichen Argumenttypen von Funktionen, die aus DLLs exportiert werden, anzugeben, indem das Attribut argtypes gesetzt wird.
argtypes muss eine Sequenz von C-Datentypen sein (die Funktion printf() ist hier wahrscheinlich kein gutes Beispiel, da sie je nach Format-String eine variable Anzahl und unterschiedliche Typen von Parametern annimmt, andererseits ist dies praktisch zum Experimentieren mit dieser Funktion).
>>> printf.argtypes = [c_char_p, c_char_p, c_int, c_double]
>>> printf(b"String '%s', Int %d, Double %f\n", b"Hi", 10, 2.2)
String 'Hi', Int 10, Double 2.200000
37
>>>
Die Angabe eines Formats schützt vor inkompatiblen Argumenttypen (genauso wie ein Prototyp für eine C-Funktion) und versucht, die Argumente in gültige Typen zu konvertieren.
>>> printf(b"%d %d %d", 1, 2, 3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ctypes.ArgumentError: argument 2: TypeError: 'int' object cannot be interpreted as ctypes.c_char_p
>>> printf(b"%s %d %f\n", b"X", 2, 3)
X 2 3.000000
13
>>>
Wenn Sie eigene Klassen definiert haben, die Sie an Funktionsaufrufe übergeben, müssen Sie eine Klassenmethode from_param() für sie implementieren, um sie in der Sequenz argtypes verwenden zu können. Die Klassenmethode from_param() empfängt das Python-Objekt, das an den Funktionsaufruf übergeben wird; sie sollte eine Typüberprüfung oder alles Notwendige durchführen, um sicherzustellen, dass dieses Objekt akzeptabel ist, und dann das Objekt selbst, sein Attribut _as_parameter_ oder was auch immer Sie in diesem Fall als C-Funktionsargument übergeben möchten, zurückgeben. Auch hier sollte das Ergebnis eine Ganzzahl, ein String, Bytes, eine ctypes-Instanz oder ein Objekt mit einem Attribut _as_parameter_ sein.
Rückgabetypen¶
Standardmäßig wird davon ausgegangen, dass Funktionen den C-int-Typ zurückgeben. Andere Rückgabetypen können durch Setzen des Attributs restype des Funktionsergebnisses angegeben werden.
Der C-Prototyp von time() lautet time_t time(time_t *). Da time_t möglicherweise einen anderen Typ als der Standardrückgabetyp int hat, sollten Sie das Attribut restype angeben.
>>> libc.time.restype = c_time_t
Die Argumenttypen können mit argtypes angegeben werden.
>>> libc.time.argtypes = (POINTER(c_time_t),)
Um die Funktion mit einem NULL-Zeiger als erstes Argument aufzurufen, verwenden Sie None.
>>> print(libc.time(None))
1150640792
Hier ist ein fortgeschritteneres Beispiel: Es verwendet die Funktion strchr(), die einen String-Zeiger und ein Zeichen erwartet und einen Zeiger auf einen String zurückgibt.
>>> strchr = libc.strchr
>>> strchr(b"abcdef", ord("d"))
8059983
>>> strchr.restype = c_char_p # c_char_p is a pointer to a string
>>> strchr(b"abcdef", ord("d"))
b'def'
>>> print(strchr(b"abcdef", ord("x")))
None
>>>
Wenn Sie die ord("x")-Aufrufe oben vermeiden möchten, können Sie das Attribut argtypes setzen, und das zweite Argument wird von einem Python-Byteobjekt mit einem Zeichen in ein C-Zeichen konvertiert.
>>> strchr.restype = c_char_p
>>> strchr.argtypes = [c_char_p, c_char]
>>> strchr(b"abcdef", b"d")
b'def'
>>> strchr(b"abcdef", b"def")
Traceback (most recent call last):
ctypes.ArgumentError: argument 2: TypeError: one character bytes, bytearray or integer expected
>>> print(strchr(b"abcdef", b"x"))
None
>>> strchr(b"abcdef", b"d")
b'def'
>>>
Sie können auch ein aufrufbares Python-Objekt (z. B. eine Funktion oder eine Klasse) als Attribut restype verwenden, wenn die Fremdfunktion eine Ganzzahl zurückgibt. Das aufrufbare Objekt wird mit der *Ganzzahl* aufgerufen, die die C-Funktion zurückgibt, und das Ergebnis dieses Aufrufs wird als Ergebnis Ihres Funktionsaufrufs verwendet. Dies ist nützlich, um Rückgabewerte auf Fehler zu prüfen und automatisch eine Ausnahme auszulösen.
>>> GetModuleHandle = windll.kernel32.GetModuleHandleA
>>> def ValidHandle(value):
... if value == 0:
... raise WinError()
... return value
...
>>>
>>> GetModuleHandle.restype = ValidHandle
>>> GetModuleHandle(None)
486539264
>>> GetModuleHandle("something silly")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in ValidHandle
OSError: [Errno 126] The specified module could not be found.
>>>
WinError ist eine Funktion, die die Windows-API FormatMessage() aufruft, um die Zeichenfolgendarstellung eines Fehlercodes zu erhalten, und eine Ausnahme *zurückgibt*. WinError nimmt einen optionalen Fehlercode-Parameter entgegen; wenn keiner verwendet wird, ruft sie GetLastError() auf, um ihn abzurufen.
Bitte beachten Sie, dass über das Attribut errcheck ein weitaus leistungsfähigerer Mechanismus zur Fehlerprüfung verfügbar ist; siehe das Referenzhandbuch für Details.
Übergeben von Zeigern (oder: Übergeben von Parametern per Referenz)¶
Manchmal erwartet eine C-API-Funktion einen *Zeiger* auf einen Datentyp als Parameter, wahrscheinlich um in den entsprechenden Speicherort zu schreiben, oder wenn die Daten zu groß sind, um per Wert übergeben zu werden. Dies wird auch als *Übergeben von Parametern per Referenz* bezeichnet.
ctypes exportiert die Funktion byref(), die zum Übergeben von Parametern per Referenz verwendet wird. Der gleiche Effekt kann mit der Funktion pointer() erzielt werden, obwohl pointer() viel mehr Arbeit leistet, da sie ein echtes Zeigerobjekt erstellt. Daher ist es schneller, byref() zu verwenden, wenn Sie das Zeigerobjekt nicht selbst in Python benötigen.
>>> i = c_int()
>>> f = c_float()
>>> s = create_string_buffer(b'\000' * 32)
>>> print(i.value, f.value, repr(s.value))
0 0.0 b''
>>> libc.sscanf(b"1 3.14 Hello", b"%d %f %s",
... byref(i), byref(f), s)
3
>>> print(i.value, f.value, repr(s.value))
1 3.1400001049 b'Hello'
>>>
Strukturen und Unions¶
Strukturen und Unions müssen von den Basisklassen Structure und Union ableiten, die im Modul ctypes definiert sind. Jede Unterklasse muss ein Attribut _fields_ definieren. _fields_ muss eine Liste von *2-Tupeln* sein, die einen *Feldnamen* und einen *Feldtyp* enthalten.
Der Feldtyp muss ein ctypes-Typ sein, wie z. B. c_int, oder ein anderer abgeleiteter ctypes-Typ: Struktur, Union, Array, Zeiger.
Hier ist ein einfaches Beispiel für eine POINT-Struktur, die zwei Ganzzahlen namens *x* und *y* enthält und auch zeigt, wie eine Struktur im Konstruktor initialisiert wird.
>>> from ctypes import *
>>> class POINT(Structure):
... _fields_ = [("x", c_int),
... ("y", c_int)]
...
>>> point = POINT(10, 20)
>>> print(point.x, point.y)
10 20
>>> point = POINT(y=5)
>>> print(point.x, point.y)
0 5
>>> POINT(1, 2, 3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: too many initializers
>>>
Sie können jedoch wesentlich komplexere Strukturen aufbauen. Eine Struktur kann selbst andere Strukturen enthalten, indem sie eine Struktur als Feldtyp verwendet.
Hier ist eine RECT-Struktur, die zwei POINTs namens *upperleft* und *lowerright* enthält.
>>> class RECT(Structure):
... _fields_ = [("upperleft", POINT),
... ("lowerright", POINT)]
...
>>> rc = RECT(point)
>>> print(rc.upperleft.x, rc.upperleft.y)
0 5
>>> print(rc.lowerright.x, rc.lowerright.y)
0 0
>>>
Verschachtelte Strukturen können auch auf verschiedene Weise im Konstruktor initialisiert werden.
>>> r = RECT(POINT(1, 2), POINT(3, 4))
>>> r = RECT((1, 2), (3, 4))
Feld-***Deskriptoren*** können von der *Klasse* abgerufen werden; sie sind nützlich zur Fehlersuche, da sie nützliche Informationen liefern können. Siehe CField.
>>> POINT.x
<ctypes.CField 'x' type=c_int, ofs=0, size=4>
>>> POINT.y
<ctypes.CField 'y' type=c_int, ofs=4, size=4>
>>>
Warnung
ctypes unterstützt nicht das Übergeben von Unions oder Strukturen mit Bitfeldern per Wert an Funktionen. Während dies auf 32-Bit-x86 funktionieren mag, ist es nicht garantiert, dass es im Allgemeinen funktioniert. Unions und Strukturen mit Bitfeldern sollten immer per Zeiger an Funktionen übergeben werden.
Struktur-/Union-Layout, Ausrichtung und Byte-Reihenfolge¶
Standardmäßig werden Struktur- und Union-Felder so angeordnet, wie es der C-Compiler tut. Es ist möglich, dieses Verhalten vollständig zu überschreiben, indem ein Klassenattribut _layout_ in der Unterklassendefinition angegeben wird; siehe die Attributdokumentation für Details.
Es ist möglich, die maximale Ausrichtung für die Felder und/oder die Struktur selbst anzugeben, indem die Klassenattribute _pack_ und/oder _align_ gesetzt werden, bzw. Siehe die Attributdokumentation für Details.
ctypes verwendet die native Byte-Reihenfolge für Strukturen und Unions. Um Strukturen mit nicht-nativer Byte-Reihenfolge zu erstellen, können Sie eine der Basisklassen BigEndianStructure, LittleEndianStructure, BigEndianUnion und LittleEndianUnion verwenden. Diese Klassen dürfen keine Zeigerfelder enthalten.
Bitfelder in Strukturen und Unions¶
Es ist möglich, Strukturen und Unions zu erstellen, die Bitfelder enthalten. Bitfelder sind nur für Ganzzahlfelder möglich; die Bitbreite wird als drittes Element in den _fields_-Tupeln angegeben.
>>> class Int(Structure):
... _fields_ = [("first_16", c_int, 16),
... ("second_16", c_int, 16)]
...
>>> print(Int.first_16)
<ctypes.CField 'first_16' type=c_int, ofs=0, bit_size=16, bit_offset=0>
>>> print(Int.second_16)
<ctypes.CField 'second_16' type=c_int, ofs=0, bit_size=16, bit_offset=16>
Es ist wichtig zu beachten, dass die Zuweisung und das Layout von Bitfeldern im Speicher nicht als C-Standard definiert sind; ihre Implementierung ist compilerabhängig. Standardmäßig versucht Python, das Verhalten eines „nativen“ Compilers für die aktuelle Plattform nachzuahmen. Einzelheiten zum Standardverhalten und wie man es ändert, finden Sie im Attribut _layout_.
Arrays¶
Arrays sind Sequenzen, die eine feste Anzahl von Instanzen desselben Typs enthalten.
Der empfohlene Weg zur Erstellung von Array-Typen ist die Multiplikation eines Datentyps mit einer positiven Ganzzahl.
TenPointsArrayType = POINT * 10
Hier ist ein Beispiel für einen etwas künstlichen Datentyp, eine Struktur, die 4 POINTs neben anderem enthält.
>>> from ctypes import *
>>> class POINT(Structure):
... _fields_ = ("x", c_int), ("y", c_int)
...
>>> class MyStruct(Structure):
... _fields_ = [("a", c_int),
... ("b", c_float),
... ("point_array", POINT * 4)]
>>>
>>> print(len(MyStruct().point_array))
4
>>>
Instanzen werden auf die übliche Weise erstellt, indem die Klasse aufgerufen wird.
arr = TenPointsArrayType()
for pt in arr:
print(pt.x, pt.y)
Der obige Code druckt eine Reihe von Zeilen mit 0 0, da der Array-Inhalt mit Nullen initialisiert wird.
Initialisierer des richtigen Typs können ebenfalls angegeben werden.
>>> from ctypes import *
>>> TenIntegers = c_int * 10
>>> ii = TenIntegers(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
>>> print(ii)
<c_long_Array_10 object at 0x...>
>>> for i in ii: print(i, end=" ")
...
1 2 3 4 5 6 7 8 9 10
>>>
Zeiger¶
Zeigerinstanzen werden durch Aufrufen der Funktion pointer() auf einen ctypes-Typ erstellt.
>>> from ctypes import *
>>> i = c_int(42)
>>> pi = pointer(i)
>>>
Zeigerinstanzen haben ein Attribut contents, das das Objekt zurückgibt, auf das der Zeiger zeigt, also das `i`-Objekt von oben.
>>> pi.contents
c_long(42)
>>>
Beachten Sie, dass ctypes keine OOR (Original Object Return) hat; es konstruiert bei jedem Abruf eines Attributs ein neues, gleichwertiges Objekt.
>>> pi.contents is i
False
>>> pi.contents is pi.contents
False
>>>
Das Zuweisen einer anderen c_int-Instanz zum `contents`-Attribut des Zeigers würde dazu führen, dass der Zeiger auf die Speicherstelle zeigt, an der diese gespeichert ist.
>>> i = c_int(99)
>>> pi.contents = i
>>> pi.contents
c_long(99)
>>>
Zeigerinstanzen können auch mit ganzen Zahlen indiziert werden.
>>> pi[0]
99
>>>
Das Zuweisen zu einem ganzzahligen Index ändert den Wert, auf den gezeigt wird.
>>> print(i)
c_long(99)
>>> pi[0] = 22
>>> print(i)
c_long(22)
>>>
Es ist auch möglich, andere Indizes als 0 zu verwenden, aber man muss wissen, was man tut, genau wie in C: Man kann auf beliebige Speicherstellen zugreifen oder diese ändern. Im Allgemeinen verwendet man diese Funktion nur, wenn man einen Zeiger von einer C-Funktion erhält und *weiß*, dass der Zeiger tatsächlich auf ein Array und nicht auf ein einzelnes Element zeigt.
Hinter den Kulissen tut die Funktion pointer() mehr als nur Zeigerinstanzen zu erstellen; sie muss zuerst Zeiger-*Typen* erstellen. Dies geschieht mit der Funktion POINTER(), die jeden ctypes-Typ akzeptiert und einen neuen Typ zurückgibt.
>>> PI = POINTER(c_int)
>>> PI
<class 'ctypes.LP_c_long'>
>>> PI(42)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: expected c_long instead of int
>>> PI(c_int(42))
<ctypes.LP_c_long object at 0x...>
>>>
Das Aufrufen des Zeigertyps ohne Argument erstellt einen NULL-Zeiger. NULL-Zeiger haben einen Wahrheitswert von False.
>>> null_ptr = POINTER(c_int)()
>>> print(bool(null_ptr))
False
>>>
ctypes prüft auf NULL beim Dereferenzieren von Zeigern (aber das Dereferenzieren ungültiger, nicht-NULL-Zeiger würde Python zum Absturz bringen).
>>> null_ptr[0]
Traceback (most recent call last):
....
ValueError: NULL pointer access
>>>
>>> null_ptr[0] = 1234
Traceback (most recent call last):
....
ValueError: NULL pointer access
>>>
Thread-Sicherheit ohne den GIL¶
Ab Python 3.13 kann der GIL in freethreaded Builds deaktiviert werden. In ctypes sind Lese- und Schreibzugriffe auf ein einzelnes Objekt gleichzeitig sicher, aber nicht über mehrere Objekte hinweg.
>>> number = c_int(42) >>> pointer_a = pointer(number) >>> pointer_b = pointer(number)
Im obigen Beispiel ist es nur dann sicher, wenn ein Objekt gleichzeitig von mehreren Threads gelesen und geschrieben wird, wenn der GIL deaktiviert ist. Daher kann pointer_a zwischen mehreren Threads geteilt und beschrieben werden, aber nur, wenn pointer_b nicht dasselbe versucht. Wenn dies ein Problem darstellt, sollten Sie eine threading.Lock zur Synchronisierung des Speicherzugriffs verwenden.
>>> import threading >>> lock = threading.Lock() >>> # Thread 1 >>> with lock: ... pointer_a.contents = 24 >>> # Thread 2 >>> with lock: ... pointer_b.contents = 42
Typkonvertierungen¶
Normalerweise führt ctypes eine strenge Typenprüfung durch. Das bedeutet, wenn Sie POINTER(c_int) in der argtypes-Liste einer Funktion oder als Typ eines Mitglieds in einer Strukturdefinition haben, werden nur Instanzen genau desselben Typs akzeptiert. Es gibt einige Ausnahmen von dieser Regel, bei denen ctypes andere Objekte akzeptiert. Sie können beispielsweise kompatible Array-Instanzen anstelle von Zeigertypen übergeben. Für POINTER(c_int) akzeptiert ctypes also ein Array von c_int.
>>> class Bar(Structure):
... _fields_ = [("count", c_int), ("values", POINTER(c_int))]
...
>>> bar = Bar()
>>> bar.values = (c_int * 3)(1, 2, 3)
>>> bar.count = 3
>>> for i in range(bar.count):
... print(bar.values[i])
...
1
2
3
>>>
Wenn ein Funktionsargument in argtypes explizit als Zeigertyp deklariert ist (z. B. POINTER(c_int)), kann ein Objekt des referenzierten Typs (in diesem Fall c_int) an die Funktion übergeben werden. ctypes wendet in diesem Fall automatisch die erforderliche byref()-Konvertierung an.
Um ein POINTER-Typfeld auf NULL zu setzen, können Sie None zuweisen.
>>> bar.values = None
>>>
Manchmal hat man Instanzen inkompatibler Typen. In C kann man einen Typ in einen anderen Typ umwandeln. ctypes stellt eine Funktion cast() bereit, die auf die gleiche Weise verwendet werden kann. Die oben definierte Struktur Bar akzeptiert POINTER(c_int)-Zeiger oder c_int-Arrays für ihr values-Feld, aber keine Instanzen anderer Typen.
>>> bar.values = (c_byte * 4)()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: incompatible types, c_byte_Array_4 instance instead of LP_c_long instance
>>>
Für diese Fälle ist die Funktion cast() nützlich.
Die Funktion cast() kann verwendet werden, um eine ctypes-Instanz in einen Zeiger auf einen anderen ctypes-Datentyp umzuwandeln. cast() nimmt zwei Parameter entgegen: ein ctypes-Objekt, das ein Zeiger irgendeiner Art ist oder in einen solchen umgewandelt werden kann, und einen ctypes-Zeigertyp. Sie gibt eine Instanz des zweiten Arguments zurück, die denselben Speicherblock wie das erste Argument referenziert.
>>> a = (c_byte * 4)()
>>> cast(a, POINTER(c_int))
<ctypes.LP_c_long object at ...>
>>>
Somit kann cast() verwendet werden, um das Feld values der Struktur Bar zuzuweisen.
>>> bar = Bar()
>>> bar.values = cast((c_byte * 4)(), POINTER(c_int))
>>> print(bar.values[0])
0
>>>
Unvollständige Typen¶
Unvollständige Typen sind Strukturen, Unions oder Arrays, deren Mitglieder noch nicht spezifiziert sind. In C werden sie durch Vorwärtsdeklarationen spezifiziert, die später definiert werden.
struct cell; /* forward declaration */
struct cell {
char *name;
struct cell *next;
};
Die direkte Übersetzung in ctypes-Code wäre diese, aber sie funktioniert nicht.
>>> class cell(Structure):
... _fields_ = [("name", c_char_p),
... ("next", POINTER(cell))]
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in cell
NameError: name 'cell' is not defined
>>>
da die neue Klasse class cell in der Klassendefinition selbst nicht verfügbar ist. In ctypes können wir die Klasse cell definieren und das Attribut _fields_ später, nach der Klassendefinition, setzen.
>>> from ctypes import *
>>> class cell(Structure):
... pass
...
>>> cell._fields_ = [("name", c_char_p),
... ("next", POINTER(cell))]
>>>
Versuchen wir es. Wir erstellen zwei Instanzen von cell, lassen sie aufeinander zeigen und folgen dann ein paar Mal der Zeigerkette.
>>> c1 = cell()
>>> c1.name = b"foo"
>>> c2 = cell()
>>> c2.name = b"bar"
>>> c1.next = pointer(c2)
>>> c2.next = pointer(c1)
>>> p = c1
>>> for i in range(8):
... print(p.name, end=" ")
... p = p.next[0]
...
foo bar foo bar foo bar foo bar
>>>
Callback-Funktionen¶
ctypes ermöglicht die Erstellung von C-aufrufbaren Funktionszeigern aus Python-Aufrufbaren. Diese werden manchmal als Callback-Funktionen bezeichnet.
Zuerst müssen Sie eine Klasse für die Callback-Funktion erstellen. Die Klasse kennt die Aufrufkonvention, den Rückgabetyp sowie die Anzahl und die Typen der Argumente, die diese Funktion empfangen wird.
Die Factory-Funktion CFUNCTYPE() erstellt Typen für Callback-Funktionen mit der cdecl-Aufrufkonvention. Unter Windows erstellt die Factory-Funktion WINFUNCTYPE() Typen für Callback-Funktionen mit der stdcall-Aufrufkonvention.
Beide dieser Factory-Funktionen werden mit dem Ergebnistyp als erstem Argument und den erwarteten Argumenttypen der Callback-Funktion als restlichen Argumenten aufgerufen.
Ich werde hier ein Beispiel präsentieren, das die Standard-C-Bibliotheksfunktion qsort() verwendet, die zum Sortieren von Elementen mithilfe einer Callback-Funktion dient. qsort() wird zum Sortieren eines Arrays von Ganzzahlen verwendet.
>>> IntArray5 = c_int * 5
>>> ia = IntArray5(5, 1, 7, 33, 99)
>>> qsort = libc.qsort
>>> qsort.restype = None
>>>
qsort() muss mit einem Zeiger auf die zu sortierenden Daten, der Anzahl der Elemente im Datenarray, der Größe eines Elements und einem Zeiger auf die Vergleichsfunktion (den Callback) aufgerufen werden. Der Callback wird dann mit zwei Zeigern auf Elemente aufgerufen und muss eine negative Ganzzahl zurückgeben, wenn das erste Element kleiner als das zweite ist, Null, wenn sie gleich sind, und andernfalls eine positive Ganzzahl.
Unser Callback-Funktion empfängt also Zeiger auf Ganzzahlen und muss eine Ganzzahl zurückgeben. Zuerst erstellen wir den Typ für die Callback-Funktion.
>>> CMPFUNC = CFUNCTYPE(c_int, POINTER(c_int), POINTER(c_int))
>>>
Zur Einführung hier ein einfacher Callback, der die übergebenen Werte anzeigt.
>>> def py_cmp_func(a, b):
... print("py_cmp_func", a[0], b[0])
... return 0
...
>>> cmp_func = CMPFUNC(py_cmp_func)
>>>
Das Ergebnis
>>> qsort(ia, len(ia), sizeof(c_int), cmp_func)
py_cmp_func 5 1
py_cmp_func 33 99
py_cmp_func 7 33
py_cmp_func 5 7
py_cmp_func 1 7
>>>
Jetzt können wir die beiden Elemente tatsächlich vergleichen und ein sinnvolles Ergebnis zurückgeben.
>>> def py_cmp_func(a, b):
... print("py_cmp_func", a[0], b[0])
... return a[0] - b[0]
...
>>>
>>> qsort(ia, len(ia), sizeof(c_int), CMPFUNC(py_cmp_func))
py_cmp_func 5 1
py_cmp_func 33 99
py_cmp_func 7 33
py_cmp_func 1 7
py_cmp_func 5 7
>>>
Wie wir leicht überprüfen können, ist unser Array jetzt sortiert.
>>> for i in ia: print(i, end=" ")
...
1 5 7 33 99
>>>
Die Funktions-Factories können als Decorator-Factories verwendet werden, daher können wir auch Folgendes schreiben:
>>> @CFUNCTYPE(c_int, POINTER(c_int), POINTER(c_int))
... def py_cmp_func(a, b):
... print("py_cmp_func", a[0], b[0])
... return a[0] - b[0]
...
>>> qsort(ia, len(ia), sizeof(c_int), py_cmp_func)
py_cmp_func 5 1
py_cmp_func 33 99
py_cmp_func 7 33
py_cmp_func 1 7
py_cmp_func 5 7
>>>
Hinweis
Stellen Sie sicher, dass Sie Referenzen auf CFUNCTYPE()-Objekte behalten, solange sie aus C-Code verwendet werden. ctypes tut dies nicht, und wenn Sie es nicht tun, könnten sie vom Garbage Collector eingesammelt werden, was Ihr Programm zum Absturz bringt, wenn ein Callback erfolgt.
Beachten Sie außerdem, dass, wenn die Callback-Funktion in einem Thread aufgerufen wird, der außerhalb der Kontrolle von Python erstellt wurde (z. B. durch den Fremdcode, der den Callback aufruft), ctypes bei jeder Invokation einen neuen Dummy-Python-Thread erstellt. Dieses Verhalten ist für die meisten Zwecke korrekt, bedeutet aber, dass Werte, die mit threading.local gespeichert werden, über verschiedene Callbacks hinweg *nicht* erhalten bleiben, selbst wenn diese Aufrufe vom selben C-Thread aus erfolgen.
Zugriff auf aus DLLs exportierte Werte¶
Einige Shared Libraries exportieren nicht nur Funktionen, sondern auch Variablen. Ein Beispiel in der Python-Bibliothek selbst ist Py_Version, die Versionsnummer der Python-Laufzeit, kodiert in einer einzigen Konstanten Ganzzahl.
ctypes kann solche Werte mit den Klassenmethoden in_dll() des Typs abrufen. *pythonapi* ist ein vordefiniertes Symbol, das Zugriff auf die Python C API bietet.
>>> version = ctypes.c_int.in_dll(ctypes.pythonapi, "Py_Version")
>>> print(hex(version.value))
0x30c00a0
Ein erweitertes Beispiel, das auch die Verwendung von Zeigern demonstriert, greift auf den von Python exportierten Zeiger PyImport_FrozenModules zu.
Zitieren der Dokumentation für diesen Wert.
Dieser Zeiger wird initialisiert, um auf ein Array von
_frozen-Datensätzen zu zeigen, die durch einen Datensatz abgeschlossen werden, dessen Member alleNULLoder Null sind. Wenn ein "eingefrorenes" Modul importiert wird, wird es in dieser Tabelle gesucht. Drittanbietercode könnte damit Tricks machen, um eine dynamisch erstellte Sammlung von "eingefrorenen" Modulen bereitzustellen.
Die Manipulation dieses Zeigers könnte also sogar nützlich sein. Um die Beispielgröße zu begrenzen, zeigen wir nur, wie diese Tabelle mit ctypes gelesen werden kann.
>>> from ctypes import *
>>>
>>> class struct_frozen(Structure):
... _fields_ = [("name", c_char_p),
... ("code", POINTER(c_ubyte)),
... ("size", c_int),
... ("get_code", POINTER(c_ubyte)), # Function pointer
... ]
...
>>>
Wir haben den Datentyp _frozen definiert, sodass wir den Zeiger auf die Tabelle erhalten können.
>>> FrozenTable = POINTER(struct_frozen)
>>> table = FrozenTable.in_dll(pythonapi, "_PyImport_FrozenBootstrap")
>>>
Da table ein pointer auf das Array von struct_frozen-Datensätzen ist, können wir es durchlaufen, aber wir müssen sicherstellen, dass unsere Schleife endet, da Zeiger keine Größe haben. Früher oder später würde es wahrscheinlich mit einer Zugriffsverletzung oder Ähnlichem abstürzen, daher ist es besser, die Schleife zu beenden, wenn wir auf den NULL-Eintrag stoßen.
>>> for item in table:
... if item.name is None:
... break
... print(item.name.decode("ascii"), item.size)
...
_frozen_importlib 31764
_frozen_importlib_external 41499
zipimport 12345
>>>
Die Tatsache, dass das Standard-Python ein "eingefrorenes" Modul und ein "eingefrorenes" Paket hat (angezeigt durch das negative size-Mitglied), ist nicht gut bekannt; es wird nur zum Testen verwendet. Probieren Sie es mit import __hello__ aus, zum Beispiel.
Überraschungen¶
Es gibt einige Kanten in ctypes, bei denen Sie etwas anderes erwarten als das, was tatsächlich passiert.
Betrachten Sie das folgende Beispiel.
>>> from ctypes import *
>>> class POINT(Structure):
... _fields_ = ("x", c_int), ("y", c_int)
...
>>> class RECT(Structure):
... _fields_ = ("a", POINT), ("b", POINT)
...
>>> p1 = POINT(1, 2)
>>> p2 = POINT(3, 4)
>>> rc = RECT(p1, p2)
>>> print(rc.a.x, rc.a.y, rc.b.x, rc.b.y)
1 2 3 4
>>> # now swap the two points
>>> rc.a, rc.b = rc.b, rc.a
>>> print(rc.a.x, rc.a.y, rc.b.x, rc.b.y)
3 4 3 4
>>>
Hm. Wir hätten sicherlich erwartet, dass die letzte Anweisung 3 4 1 2 ausgibt. Was ist passiert? Hier sind die Schritte der Zeile rc.a, rc.b = rc.b, rc.a oben:
>>> temp0, temp1 = rc.b, rc.a
>>> rc.a = temp0
>>> rc.b = temp1
>>>
Beachten Sie, dass temp0 und temp1 Objekte sind, die immer noch den internen Puffer des obigen rc-Objekts verwenden. Das Ausführen von rc.a = temp0 kopiert den Pufferinhalt von temp0 in den Puffer von rc. Dies wiederum ändert den Inhalt von temp1. Die letzte Zuweisung rc.b = temp1 hat also nicht den erwarteten Effekt.
Denken Sie daran, dass das Abrufen von Unterobjekten aus Strukturen, Unions und Arrays das Unterobjekt nicht *kopiert*, sondern ein Wrapper-Objekt abruft, das auf den Puffer des Stammobjekts zugreift.
Ein weiteres Beispiel, das sich anders verhalten kann als erwartet, ist dieses:
>>> s = c_char_p()
>>> s.value = b"abc def ghi"
>>> s.value
b'abc def ghi'
>>> s.value is s.value
False
>>>
Hinweis
Objekte, die von c_char_p instanziiert werden, können nur ihren Wert auf Bytes oder Ganzzahlen setzen.
Warum gibt es False aus? ctypes-Instanzen sind Objekte, die einen Speicherblock plus einige Deskriptoren enthalten, die auf den Inhalt des Speichers zugreifen. Das Speichern eines Python-Objekts im Speicherblock speichert nicht das Objekt selbst, stattdessen werden die contents des Objekts gespeichert. Der Abruf der Inhalte konstruiert jedes Mal ein neues Python-Objekt!
Datentypen variabler Größe¶
ctypes bietet einige Unterstützung für Arrays und Strukturen variabler Größe.
Die Funktion resize() kann verwendet werden, um den Speicherpuffer eines vorhandenen ctypes-Objekts zu ändern. Die Funktion nimmt das Objekt als erstes Argument und die gewünschte Größe in Bytes als zweites Argument entgegen. Der Speicherblock kann nicht kleiner als der natürliche Speicherblock gemacht werden, der durch den Typ des Objekts spezifiziert ist; wenn dies versucht wird, wird ein ValueError ausgelöst.
>>> short_array = (c_short * 4)()
>>> print(sizeof(short_array))
8
>>> resize(short_array, 4)
Traceback (most recent call last):
...
ValueError: minimum size is 8
>>> resize(short_array, 32)
>>> sizeof(short_array)
32
>>> sizeof(type(short_array))
8
>>>
Das ist nett und in Ordnung, aber wie greift man auf die zusätzlichen Elemente zu, die in diesem Array enthalten sind? Da der Typ immer noch nur über 4 Elemente Bescheid weiß, erhalten wir Fehler beim Zugriff auf andere Elemente.
>>> short_array[:]
[0, 0, 0, 0]
>>> short_array[7]
Traceback (most recent call last):
...
IndexError: invalid index
>>>
Eine andere Möglichkeit, Datentypen variabler Größe mit ctypes zu verwenden, ist die Nutzung der dynamischen Natur von Python und die (Neu-)Definition des Datentyps, nachdem die erforderliche Größe bereits bekannt ist, von Fall zu Fall.
ctypes Referenz¶
Externe Funktionen¶
Wie im vorherigen Abschnitt erläutert, kann auf externe Funktionen als Attribute geladener Shared Libraries zugegriffen werden. Die auf diese Weise erstellten Funktions-Objekte akzeptieren standardmäßig eine beliebige Anzahl von Argumenten, akzeptieren beliebige ctypes-Dateninstanzen als Argumente und geben den vom Bibliothekslader spezifizierten Standard-Ergebnistyp zurück.
Sie sind Instanzen einer privaten lokalen Klasse _FuncPtr (nicht in ctypes exponiert), die von der privaten Klasse _CFuncPtr erbt.
>>> import ctypes
>>> lib = ctypes.CDLL(None)
>>> issubclass(lib._FuncPtr, ctypes._CFuncPtr)
True
>>> lib._FuncPtr is ctypes._CFuncPtr
False
- class ctypes._CFuncPtr¶
Basisklasse für C-aufrufbare externe Funktionen.
Instanzen von externen Funktionen sind ebenfalls C-kompatible Datentypen; sie repräsentieren C-Funktionszeiger.
Dieses Verhalten kann durch Zuweisung zu speziellen Attributen des externen Funktions-Objekts angepasst werden.
- restype¶
Weisen Sie einen ctypes-Typ zu, um den Ergebnistyp der externen Funktion anzugeben. Verwenden Sie
Nonefür void, eine Funktion, die nichts zurückgibt.Es ist möglich, ein aufrufbares Python-Objekt zuzuweisen, das kein ctypes-Typ ist. In diesem Fall wird angenommen, dass die Funktion eine C int zurückgibt, und das aufrufbare Objekt wird mit dieser Ganzzahl aufgerufen, was eine weitere Verarbeitung oder Fehlerprüfung ermöglicht. Die Verwendung ist veraltet. Für flexiblere Nachbearbeitung oder Fehlerprüfung verwenden Sie einen ctypes-Datentyp als
restypeund weisen Sie ein aufrufbares Objekt dem Attributerrcheckzu.
- argtypes¶
Weisen Sie ein Tupel von ctypes-Typen zu, um die Argumenttypen anzugeben, die die Funktion akzeptiert. Funktionen, die die
stdcallAufrufkonvention verwenden, können nur mit der gleichen Anzahl von Argumenten wie die Länge dieses Tupels aufgerufen werden; Funktionen, die die C-Aufrufkonvention verwenden, akzeptieren auch zusätzliche, nicht spezifizierte Argumente.Wenn eine externe Funktion aufgerufen wird, wird jedes tatsächliche Argument an die Klassenmethode
from_param()der Elemente imargtypes-Tupel übergeben. Diese Methode ermöglicht die Anpassung des tatsächlichen Arguments an ein Objekt, das die externe Funktion akzeptiert. Beispielsweise konvertiert einc_char_p-Element imargtypes-Tupel einen als Argument übergebenen String gemäß den ctypes-Konvertierungsregeln in ein Bytes-Objekt.Neu: Es ist jetzt möglich, Elemente in argtypes aufzunehmen, die keine ctypes-Typen sind. Jedes Element muss jedoch eine
from_param()-Methode haben, die einen als Argument verwendbaren Wert (Ganzzahl, String, ctypes-Instanz) zurückgibt. Dies ermöglicht die Definition von Adaptern, die benutzerdefinierte Objekte als Funktionsparameter adaptieren können.
- errcheck¶
Weisen Sie eine Python-Funktion oder ein anderes aufrufbares Objekt diesem Attribut zu. Das aufrufbare Objekt wird mit drei oder mehr Argumenten aufgerufen
- callable(result, func, arguments)
result ist das, was die externe Funktion zurückgibt, wie durch das Attribut
restypespezifiziert.func ist das externe Funktions-Objekt selbst, dies ermöglicht die Wiederverwendung desselben aufrufbaren Objekts zur Prüfung oder Nachbearbeitung der Ergebnisse mehrerer Funktionen.
arguments ist ein Tupel, das die Parameter enthält, die ursprünglich an den Funktionsaufruf übergeben wurden. Dies ermöglicht die Spezialisierung des Verhaltens auf die verwendeten Argumente.
Das Objekt, das diese Funktion zurückgibt, wird vom externen Funktionsaufruf zurückgegeben, aber sie kann auch den Ergebniswert prüfen und eine Ausnahme auslösen, wenn der externe Funktionsaufruf fehlgeschlagen ist.
Unter Windows werden Systemausnahmen, die von einem externen Funktionsaufruf ausgelöst werden (z. B. aufgrund einer Zugriffsverletzung), abgefangen und durch eine geeignete Python-Ausnahme ersetzt. Des Weiteren wird ein Auditing-Ereignis ctypes.set_exception mit dem Argument code ausgelöst, was einem Audit-Hook ermöglicht, die Ausnahme durch seine eigene zu ersetzen.
Einige Möglichkeiten, externe Funktionsaufrufe aufzurufen, sowie einige der Funktionen in diesem Modul, können ein Auditing-Ereignis ctypes.call_function mit den Argumenten function pointer und arguments auslösen.
Funktionsprototypen¶
Externe Funktionen können auch durch Instanziierung von Funktionsprototypen erstellt werden. Funktionsprototypen ähneln Funktionsprototypen in C; sie beschreiben eine Funktion (Rückgabetyp, Argumenttypen, Aufrufkonvention), ohne eine Implementierung zu definieren. Die Factory-Funktionen müssen mit dem gewünschten Rückgabetyp und den Argumenttypen der Funktion aufgerufen werden und können als Dekorator-Fabriken verwendet werden, und als solche auf Funktionen über die @wrapper-Syntax angewendet werden. Beispiele finden Sie unter Callback-Funktionen.
- ctypes.CFUNCTYPE(restype, *argtypes, use_errno=False, use_last_error=False)¶
Der zurückgegebene Funktionsprototyp erstellt Funktionen, die die Standard-C-Aufrufkonvention verwenden. Die Funktion gibt den GIL während des Aufrufs frei. Wenn use_errno auf true gesetzt ist, wird die private Kopie der Systemvariable
errnovon ctypes mit dem tatsächlichen Wert vonerrnovor und nach dem Aufruf vertauscht. use_last_error tut dasselbe für den Windows-Fehlercode.
- ctypes.WINFUNCTYPE(restype, *argtypes, use_errno=False, use_last_error=False)¶
Der zurückgegebene Funktionsprototyp erstellt Funktionen, die die
stdcallAufrufkonvention verwenden. Die Funktion gibt den GIL während des Aufrufs frei. use_errno und use_last_error haben die gleiche Bedeutung wie oben.Verfügbarkeit: Windows
- ctypes.PYFUNCTYPE(restype, *argtypes)¶
Der zurückgegebene Funktionsprototyp erstellt Funktionen, die die Python-Aufrufkonvention verwenden. Die Funktion gibt den GIL während des Aufrufs *nicht* frei.
Funktionsprototypen, die von diesen Factory-Funktionen erstellt wurden, können auf verschiedene Weise instanziiert werden, abhängig vom Typ und der Anzahl der Parameter im Aufruf.
- prototype(address)
Gibt eine externe Funktion an der angegebenen Adresse zurück, die eine Ganzzahl sein muss.
- prototype(callable)
Erstellt eine C-aufrufbare Funktion (eine Callback-Funktion) aus einem Python-callable.
- prototype(func_spec[, paramflags])
Gibt eine externe Funktion zurück, die von einer Shared Library exportiert wird. func_spec muss ein 2-Tupel sein
(name_or_ordinal, library). Das erste Element ist der Name der exportierten Funktion als String oder die Ordinalzahl der exportierten Funktion als kleine Ganzzahl. Das zweite Element ist die Shared Library-Instanz.
- prototype(vtbl_index, name[, paramflags[, iid]])
Gibt eine externe Funktion zurück, die eine COM-Methode aufruft. vtbl_index ist der Index in der virtuellen Funktionstabelle, eine kleine nicht-negative Ganzzahl. name ist der Name der COM-Methode. iid ist ein optionaler Zeiger auf die Schnittstellenkennung, die in der erweiterten Fehlerberichterstattung verwendet wird.
Wenn iid nicht angegeben ist, wird eine
OSErrorausgelöst, wenn der COM-Methodenaufruf fehlschlägt. Wenn iid angegeben ist, wird stattdessen eineCOMErrorausgelöst.COM-Methoden verwenden eine spezielle Aufrufkonvention: Sie erfordern zusätzlich zu den im Tupel
argtypesspezifizierten Parametern einen Zeiger auf die COM-Schnittstelle als erstes Argument.Verfügbarkeit: Windows
Der optionale Parameter paramflags erstellt externe Funktions-Wrapper mit viel mehr Funktionalität als die oben beschriebenen Features.
paramflags muss ein Tupel gleicher Länge wie argtypes sein.
Jeder Eintrag in diesem Tupel enthält weitere Informationen zu einem Parameter und muss ein Tupel aus einem, zwei oder drei Elementen sein.
Das erste Element ist eine Ganzzahl, die eine Kombination von Richtungsflags für den Parameter enthält.
- 1
Spezifiziert einen Eingabeparameter für die Funktion.
- 2
Ausgabeparameter. Die externe Funktion füllt einen Wert ein.
- 4
Eingabeparameter, der standardmäßig auf die Ganzzahl Null gesetzt ist.
Das optionale zweite Element ist der Parametername als String. Wenn dies angegeben ist, kann die externe Funktion mit benannten Parametern aufgerufen werden.
Das optionale dritte Element ist der Standardwert für diesen Parameter.
Das folgende Beispiel zeigt, wie die Windows-Funktion MessageBoxW so gekapselt wird, dass sie Standardparameter und benannte Argumente unterstützt. Die C-Deklaration aus der Windows-Header-Datei lautet:
WINUSERAPI int WINAPI
MessageBoxW(
HWND hWnd,
LPCWSTR lpText,
LPCWSTR lpCaption,
UINT uType);
Hier ist die Kapselung mit ctypes.
>>> from ctypes import c_int, WINFUNCTYPE, windll
>>> from ctypes.wintypes import HWND, LPCWSTR, UINT
>>> prototype = WINFUNCTYPE(c_int, HWND, LPCWSTR, LPCWSTR, UINT)
>>> paramflags = (1, "hwnd", 0), (1, "text", "Hi"), (1, "caption", "Hello from ctypes"), (1, "flags", 0)
>>> MessageBox = prototype(("MessageBoxW", windll.user32), paramflags)
Die externe Funktion MessageBox kann jetzt auf folgende Weise aufgerufen werden.
>>> MessageBox()
>>> MessageBox(text="Spam, spam, spam")
>>> MessageBox(flags=2, text="foo bar")
Ein zweites Beispiel demonstriert Ausgabeparameter. Die Win32-Funktion GetWindowRect ruft die Abmessungen eines angegebenen Fensters ab, indem sie diese in eine RECT-Struktur kopiert, die vom Aufrufer bereitgestellt werden muss. Hier ist die C-Deklaration.
WINUSERAPI BOOL WINAPI
GetWindowRect(
HWND hWnd,
LPRECT lpRect);
Hier ist die Kapselung mit ctypes.
>>> from ctypes import POINTER, WINFUNCTYPE, windll, WinError
>>> from ctypes.wintypes import BOOL, HWND, RECT
>>> prototype = WINFUNCTYPE(BOOL, HWND, POINTER(RECT))
>>> paramflags = (1, "hwnd"), (2, "lprect")
>>> GetWindowRect = prototype(("GetWindowRect", windll.user32), paramflags)
>>>
Funktionen mit Ausgabeparametern geben automatisch den Wert des Ausgabeparameters zurück, wenn es einen einzelnen gibt, oder ein Tupel, das die Werte der Ausgabeparameter enthält, wenn es mehrere gibt. Daher gibt die Funktion GetWindowRect nun eine RECT-Instanz zurück, wenn sie aufgerufen wird.
Ausgabeparameter können mit dem errcheck-Protokoll kombiniert werden, um weitere Ausgabeverarbeitung und Fehlerprüfung durchzuführen. Die Win32-API-Funktion GetWindowRect gibt ein BOOL zurück, um Erfolg oder Misserfolg zu signalisieren. Diese Funktion könnte also die Fehlerprüfung durchführen und eine Ausnahme auslösen, wenn der API-Aufruf fehlschlägt.
>>> def errcheck(result, func, args):
... if not result:
... raise WinError()
... return args
...
>>> GetWindowRect.errcheck = errcheck
>>>
Wenn die errcheck-Funktion das empfangene Argument-Tupel unverändert zurückgibt, setzt ctypes die normale Verarbeitung der Ausgabeparameter fort. Wenn Sie ein Tupel von Fensterkoordinaten anstelle einer RECT-Instanz zurückgeben möchten, können Sie die Felder in der Funktion abrufen und stattdessen zurückgeben; die normale Verarbeitung findet dann nicht mehr statt.
>>> def errcheck(result, func, args):
... if not result:
... raise WinError()
... rc = args[1]
... return rc.left, rc.top, rc.bottom, rc.right
...
>>> GetWindowRect.errcheck = errcheck
>>>
Hilfsfunktionen¶
- ctypes.addressof(obj)¶
Gibt die Adresse des Speicherpuffers als Ganzzahl zurück. obj muss eine Instanz eines ctypes-Typs sein.
Löst ein Auditing-Ereignis
ctypes.addressofmit dem Argumentobjaus.
- ctypes.alignment(obj_or_type)¶
Gibt die Ausrichtungsvoraussetzungen eines ctypes-Typs zurück. obj_or_type muss ein ctypes-Typ oder eine Instanz sein.
- ctypes.byref(obj[, offset])¶
Gibt einen leichtgewichtigen Zeiger auf obj zurück, der eine Instanz eines ctypes-Typs sein muss. offset ist standardmäßig Null und muss eine Ganzzahl sein, die zum internen Zeigerwert addiert wird.
byref(obj, offset)entspricht diesem C-Code.(((char *)&obj) + offset)
Das zurückgegebene Objekt kann nur als Parameter für einen Fremdfunktionsaufruf verwendet werden. Es verhält sich ähnlich wie
pointer(obj), aber die Konstruktion ist wesentlich schneller.
- ctypes.CopyComPointer(src, dst)¶
Kopiert einen COM-Zeiger von src nach dst und gibt den Windows-spezifischen
HRESULT-Wert zurück.Wenn src nicht
NULList, wird seineAddRef-Methode aufgerufen, wodurch der Referenzzähler erhöht wird.Im Gegensatz dazu wird der Referenzzähler von dst vor der Zuweisung des neuen Wertes nicht dekrementiert. Sofern dst nicht
NULList, ist der Aufrufer dafür verantwortlich, den Referenzzähler durch Aufrufen seinerRelease-Methode zu dekrementieren, wenn dies erforderlich ist.Verfügbarkeit: Windows
Hinzugefügt in Version 3.14.
- ctypes.cast(obj, type)¶
Diese Funktion ähnelt dem Cast-Operator in C. Sie gibt eine neue Instanz von type zurück, die auf denselben Speicherblock wie obj zeigt. type muss ein Zeigertyp sein und obj muss ein Objekt sein, das als Zeiger interpretiert werden kann.
- ctypes.create_string_buffer(init, size=None)¶
- ctypes.create_string_buffer(size)
Diese Funktion erstellt einen modifizierbaren Zeichenpuffer. Das zurückgegebene Objekt ist ein ctypes-Array von
c_char.Wenn size angegeben ist (und nicht
None), muss es eineintsein. Es gibt die Größe des zurückgegebenen Arrays an.Wenn das Argument init angegeben ist, muss es
bytessein. Es wird verwendet, um die Array-Elemente zu initialisieren. Bytes, die auf diese Weise nicht initialisiert wurden, werden auf Null (NUL) gesetzt.Wenn size nicht angegeben ist (oder wenn es
Noneist), wird der Puffer um ein Element größer als init gemacht, wodurch effektiv ein NUL-Terminator hinzugefügt wird.Wenn beide Argumente angegeben sind, darf size nicht kleiner als
len(init)sein.Warnung
Wenn size gleich
len(init)ist, wird kein NUL-Terminator hinzugefügt. Behandeln Sie einen solchen Puffer nicht als C-String.Zum Beispiel
>>> bytes(create_string_buffer(2)) b'\x00\x00' >>> bytes(create_string_buffer(b'ab')) b'ab\x00' >>> bytes(create_string_buffer(b'ab', 2)) b'ab' >>> bytes(create_string_buffer(b'ab', 4)) b'ab\x00\x00' >>> bytes(create_string_buffer(b'abcdef', 2)) Traceback (most recent call last): ... ValueError: byte string too long
Löst ein Auditing-Ereignis
ctypes.create_string_buffermit den Argumenteninit,sizeaus.
- ctypes.create_unicode_buffer(init, size=None)¶
- ctypes.create_unicode_buffer(size)
Diese Funktion erstellt einen modifizierbaren Unicode-Zeichenpuffer. Das zurückgegebene Objekt ist ein ctypes-Array von
c_wchar.Die Funktion nimmt dieselben Argumente wie
create_string_buffer(), außer dass init ein String sein muss und size die Anzahl derc_wcharzählt.Löst ein Auditing-Ereignis
ctypes.create_unicode_buffermit den Argumenteninit,sizeaus.
- ctypes.DllCanUnloadNow()¶
Diese Funktion ist ein Hook, der die Implementierung von In-Process-COM-Servern mit ctypes ermöglicht. Sie wird von der DllCanUnloadNow-Funktion aufgerufen, die die _ctypes-Erweiterungs-DLL exportiert.
Verfügbarkeit: Windows
- ctypes.DllGetClassObject()¶
Diese Funktion ist ein Hook, der die Implementierung von In-Process-COM-Servern mit ctypes ermöglicht. Sie wird von der DllGetClassObject-Funktion aufgerufen, die die _ctypes-Erweiterungs-DLL exportiert.
Verfügbarkeit: Windows
- ctypes.util.find_library(name)¶
Versucht, eine Bibliothek zu finden und gibt einen Pfadnamen zurück. name ist der Bibliotheksname ohne Präfix wie
lib, Suffix wie.so,.dyliboder Versionsnummer (dies ist die Form, die für die POSIX-Linker-Option-lverwendet wird). Wenn keine Bibliothek gefunden werden kann, wirdNonezurückgegeben.Die genaue Funktionalität ist systemabhängig.
- ctypes.util.find_msvcrt()¶
Gibt den Dateinamen der VC-Laufzeitbibliothek zurück, die von Python und den Erweiterungsmodulen verwendet wird. Wenn der Name der Bibliothek nicht ermittelt werden kann, wird
Nonezurückgegeben.Wenn Sie Speicher freigeben müssen, der beispielsweise von einem Erweiterungsmodul mit einem Aufruf von
free(void *)zugewiesen wurde, ist es wichtig, dass Sie die Funktion in derselben Bibliothek verwenden, die den Speicher zugewiesen hat.Verfügbarkeit: Windows
- ctypes.util.dllist()¶
Versucht, eine Liste von Pfaden der im aktuellen Prozess geladenen Shared Libraries bereitzustellen. Diese Pfade werden nicht normalisiert oder anderweitig verarbeitet. Die Funktion kann
OSErrorauslösen, wenn die zugrunde liegenden Plattform-APIs fehlschlagen. Die genaue Funktionalität ist systemabhängig.Auf den meisten Plattformen repräsentiert das erste Element der Liste die aktuelle ausführbare Datei. Es kann ein leerer String sein.
Verfügbarkeit: Windows, macOS, iOS, glibc, BSD libc, musl
Hinzugefügt in Version 3.14.
- ctypes.FormatError([code])¶
Gibt eine textuelle Beschreibung des Fehlercodes code zurück. Wenn kein Fehlercode angegeben ist, wird der letzte Fehlercode durch Aufrufen der Windows-API-Funktion
GetLastError()verwendet.Verfügbarkeit: Windows
- ctypes.GetLastError()¶
Gibt den letzten Fehlercode zurück, der von Windows im aufrufenden Thread gesetzt wurde. Diese Funktion ruft die Windows-Funktion
GetLastError()direkt auf, sie gibt nicht die private Kopie des Fehlercodes von ctypes zurück.Verfügbarkeit: Windows
- ctypes.get_errno()¶
Gibt den aktuellen Wert der privaten Kopie der Systemvariable
errnovon ctypes im aufrufenden Thread zurück.Löst ein Auditing-Ereignis
ctypes.get_errnomit keinen Argumenten aus.
- ctypes.get_last_error()¶
Gibt den aktuellen Wert der privaten Kopie der Systemvariable
LastErrorvon ctypes im aufrufenden Thread zurück.Verfügbarkeit: Windows
Löst ein Auditing-Ereignis
ctypes.get_last_errormit keinen Argumenten aus.
- ctypes.memmove(dst, src, count)¶
Entspricht der Standard-C-Bibliotheksfunktion memmove: kopiert count Bytes von src nach dst. dst und src müssen ganze Zahlen oder ctypes-Instanzen sein, die in Zeiger konvertiert werden können.
- ctypes.memset(dst, c, count)¶
Entspricht der Standard-C-Bibliotheksfunktion memset: füllt den Speicherblock an der Adresse dst mit count Bytes des Werts c. dst muss eine ganze Zahl sein, die eine Adresse angibt, oder eine ctypes-Instanz.
- ctypes.POINTER(type, /)¶
Erstellt oder gibt einen ctypes-Zeigertyp zurück. Zeigertypen werden zwischengespeichert und intern wiederverwendet, daher ist der wiederholte Aufruf dieser Funktion kostengünstig. type muss ein ctypes-Typ sein.
CPython-Implementierungsdetail: Der resultierende Zeigertyp wird im Attribut
__pointer_type__von type zwischengespeichert. Es ist möglich, dieses Attribut vor dem ersten Aufruf vonPOINTERfestzulegen, um einen benutzerdefinierten Zeigertyp festzulegen. Dies wird jedoch nicht empfohlen: Manuelles Erstellen eines geeigneten Zeigertyps ist ohne Rückgriff auf Implementierungsdetails, die sich in zukünftigen Python-Versionen ändern können, schwierig.
- ctypes.pointer(obj, /)¶
Erstellt eine neue Zeigerinstanz, die auf obj zeigt. Das zurückgegebene Objekt hat den Typ
POINTER(type(obj)).Hinweis: Wenn Sie lediglich einen Zeiger auf ein Objekt an einen Fremdfunktionsaufruf übergeben möchten, sollten Sie
byref(obj)verwenden, was wesentlich schneller ist.
- ctypes.resize(obj, size)¶
Diese Funktion ändert die Größe des internen Speicherpuffers von obj, das eine Instanz eines ctypes-Typs sein muss. Es ist nicht möglich, den Puffer kleiner zu machen als die native Größe des Typs des Objekts, wie durch
sizeof(type(obj))gegeben, aber es ist möglich, den Puffer zu vergrößern.
- ctypes.set_errno(value)¶
Setzt den aktuellen Wert der privaten Kopie der Systemvariable
errnovon ctypes im aufrufenden Thread auf value und gibt den vorherigen Wert zurück.Löst ein Auditing-Ereignis
ctypes.set_errnomit dem Argumenterrnoaus.
- ctypes.set_last_error(value)¶
Setzt den aktuellen Wert der privaten Kopie der Systemvariable
LastErrorvon ctypes im aufrufenden Thread auf value und gibt den vorherigen Wert zurück.Verfügbarkeit: Windows
Löst ein Auditing-Ereignis
ctypes.set_last_errormit dem Argumenterroraus.
- ctypes.sizeof(obj_or_type)¶
Gibt die Größe in Bytes eines ctypes-Typs oder einer Instanz eines Speicherpuffers zurück. Funktioniert wie der C-
sizeof-Operator.
- ctypes.string_at(ptr, size=-1)¶
Gibt den Byte-String an void *ptr zurück. Wenn size angegeben ist, wird es als Größe verwendet, andernfalls wird angenommen, dass der String nullterminiert ist.
Löst ein Auditing-Ereignis
ctypes.string_atmit den Argumentenptr,sizeaus.
- ctypes.WinError(code=None, descr=None)¶
Erstellt eine Instanz von
OSError. Wenn code nicht angegeben ist, wirdGetLastError()aufgerufen, um den Fehlercode zu ermitteln. Wenn descr nicht angegeben ist, wirdFormatError()aufgerufen, um eine textuelle Beschreibung des Fehlers zu erhalten.Verfügbarkeit: Windows
Geändert in Version 3.3: Es wurde früher eine Instanz von
WindowsErrorerstellt, die jetzt ein Alias fürOSErrorist.
- ctypes.wstring_at(ptr, size=-1)¶
Gibt den Wide-Character-String an void *ptr zurück. Wenn size angegeben ist, wird es als Anzahl der Zeichen des Strings verwendet, andernfalls wird angenommen, dass der String nullterminiert ist.
Löst ein Auditing-Ereignis
ctypes.wstring_atmit den Argumentenptr,sizeaus.
- ctypes.memoryview_at(ptr, size, readonly=False)¶
Gibt ein
memoryview-Objekt der Länge size zurück, das auf Speicher verweist, der bei void *ptr beginnt.Wenn readonly wahr ist, kann das zurückgegebene
memoryview-Objekt nicht verwendet werden, um den zugrunde liegenden Speicher zu ändern. (Änderungen, die auf andere Weise vorgenommen wurden, werden weiterhin im zurückgegebenen Objekt reflektiert.)Diese Funktion ähnelt
string_at()mit dem wesentlichen Unterschied, dass der angegebene Speicher nicht kopiert wird. Sie ist eine semantisch äquivalente (aber effizientere) Alternative zumemoryview((c_byte * size).from_address(ptr)). (Währendfrom_address()nur ganze Zahlen akzeptiert, kann ptr auch alsctypes.POINTERoder alsbyref()-Objekt übergeben werden.)Löst ein Auditing-Ereignis
ctypes.memoryview_atmit den Argumentenaddress,size,readonlyaus.Hinzugefügt in Version 3.14.
Datentypen¶
- class ctypes._CData¶
Diese nicht-öffentliche Klasse ist die gemeinsame Basisklasse aller ctypes-Datentypen. Unter anderem enthalten alle Instanzen von ctypes-Typen einen Speicherblock, der C-kompatible Daten enthält. Die Adresse des Speicherblocks wird von der Hilfsfunktion
addressof()zurückgegeben. Eine weitere Instanzvariable wird als_objectsexponiert; diese enthält andere Python-Objekte, die am Leben erhalten werden müssen, falls der Speicherblock Zeiger enthält.Gängige Methoden von ctypes-Datentypen, dies sind alles Klassenmethoden (genauer gesagt sind es Methoden der Metaklasse)
- from_buffer(source[, offset])¶
Diese Methode gibt eine ctypes-Instanz zurück, die den Puffer des source-Objekts teilt. Das source-Objekt muss die schreibbare Puffer-Schnittstelle unterstützen. Der optionale Parameter offset gibt einen Offset im Quellpuffer in Bytes an; der Standardwert ist null. Wenn der Quellpuffer nicht groß genug ist, wird ein
ValueErrorausgelöst.Löst ein Auditing-Ereignis
ctypes.cdata/buffermit den Argumentenpointer,size,offsetaus.
- from_buffer_copy(source[, offset])¶
Diese Methode erstellt eine ctypes-Instanz, indem der Puffer aus dem source-Objekt kopiert wird, der lesbar sein muss. Der optionale Parameter offset gibt einen Offset im Quellpuffer in Bytes an; der Standardwert ist null. Wenn der Quellpuffer nicht groß genug ist, wird ein
ValueErrorausgelöst.Löst ein Auditing-Ereignis
ctypes.cdata/buffermit den Argumentenpointer,size,offsetaus.
- from_address(address)¶
Diese Methode gibt eine ctypes-Typinstanz zurück, die den von address angegebenen Speicher verwendet, der eine ganze Zahl sein muss.
Diese Methode und andere, die diese Methode indirekt aufrufen, lösen ein Auditing-Ereignis
ctypes.cdatamit dem Argumentaddressaus.
- from_param(obj)¶
Diese Methode passt obj an einen ctypes-Typ an. Sie wird mit dem tatsächlichen Objekt aufgerufen, das in einem Fremdfunktionsaufruf verwendet wird, wenn der Typ im Tupel
argtypesder Fremdfunktion vorhanden ist; sie muss ein Objekt zurückgeben, das als Funktionsaufrufparameter verwendet werden kann.Alle ctypes-Datentypen haben eine Standardimplementierung dieser Klassenmethode, die normalerweise obj zurückgibt, wenn es sich um eine Instanz des Typs handelt. Einige Typen akzeptieren auch andere Objekte.
- in_dll(library, name)¶
Diese Methode gibt eine ctypes-Typinstanz zurück, die von einer Shared Library exportiert wird. name ist der Name des Symbols, das die Daten exportiert, library ist die geladene Shared Library.
Gängige Klassenvariablen von ctypes-Datentypen
- __pointer_type__¶
Der Zeigertyp, der durch Aufrufen von
POINTER()für den entsprechenden ctypes-Datentyp erstellt wurde. Wenn noch kein Zeigertyp erstellt wurde, fehlt das Attribut.Hinzugefügt in Version 3.14.
Gängige Instanzvariablen von ctypes-Datentypen
- _b_base_¶
Manchmal besitzen ctypes-Dateninstanzen den von ihnen enthaltenen Speicherblock nicht, sondern teilen sich einen Teil des Speicherblocks eines Basisobjekts. Das schreibgeschützte Mitglied
_b_base_ist das Wurzel-ctypes-Objekt, das den Speicherblock besitzt.
- _b_needsfree_¶
Diese schreibgeschützte Variable ist wahr, wenn die ctypes-Dateninstanz den Speicherblock selbst zugewiesen hat, andernfalls falsch.
- _objects¶
Dieses Mitglied ist entweder
Noneoder ein Wörterbuch, das Python-Objekte enthält, die am Leben erhalten werden müssen, damit der Inhalt des Speicherblocks gültig bleibt. Dieses Objekt wird nur zur Fehlersuche bereitgestellt; ändern Sie niemals den Inhalt dieses Wörterbuchs.
Grundlegende Datentypen¶
- class ctypes._SimpleCData¶
Diese nicht-öffentliche Klasse ist die Basisklasse aller grundlegenden ctypes-Datentypen. Sie wird hier erwähnt, weil sie die gemeinsamen Attribute der grundlegenden ctypes-Datentypen enthält.
_SimpleCDataist eine Unterklasse von_CDataund erbt daher deren Methoden und Attribute. ctypes-Datentypen, die keine Zeiger sind und keine Zeiger enthalten, können nun serialisiert werden.Instanzen haben ein einziges Attribut
- value¶
Dieses Attribut enthält den tatsächlichen Wert der Instanz. Für Ganzzahl- und Zeigertypen ist es eine Ganzzahl, für Zeichentypen ist es ein einzelnes Zeichen als Bytes-Objekt oder String, für Zeichenzeigertypen ist es ein Python-Bytes-Objekt oder ein String.
Wenn das Attribut
valuevon einer ctypes-Instanz abgerufen wird, wird normalerweise jedes Mal ein neues Objekt zurückgegeben.ctypesimplementiert **keine** Rückgabe des Originalobjekts, es wird immer ein neues Objekt konstruiert. Dasselbe gilt für alle anderen ctypes-Objektinstanzen.
Grundlegende Datentypen, wenn sie als Ergebnisse eines Fremdfunktionsaufrufs zurückgegeben werden oder z. B. durch Abrufen von Strukturfeldmitgliedern oder Array-Elementen, werden transparent in native Python-Typen konvertiert. Anders ausgedrückt: Wenn eine Fremdfunktion einen restype von c_char_p hat, erhalten Sie immer ein Python-Bytes-Objekt, **nicht** eine Instanz von c_char_p.
Unterklassen von grundlegenden Datentypen erben dieses Verhalten **nicht**. Wenn also der restype einer Fremdfunktion eine Unterklasse von c_void_p ist, erhalten Sie von dem Funktionsaufruf eine Instanz dieser Unterklasse. Natürlich können Sie den Wert des Zeigers abrufen, indem Sie auf das Attribut value zugreifen.
Dies sind die grundlegenden ctypes-Datentypen
- class ctypes.c_byte¶
Stellt den C-Datentyp signed char dar und interpretiert den Wert als kleine Ganzzahl. Der Konstruktor akzeptiert einen optionalen Ganzzahl-Initialisierer; es wird keine Überlaufprüfung durchgeführt.
- class ctypes.c_char¶
Stellt den C-Datentyp char dar und interpretiert den Wert als einzelnes Zeichen. Der Konstruktor akzeptiert einen optionalen String-Initialisierer; die Länge des Strings muss genau ein Zeichen betragen.
- class ctypes.c_char_p¶
Stellt den C-Datentyp char* dar, wenn er auf einen nullterminierten String zeigt. Für einen allgemeinen Zeichenzeiger, der auch auf binäre Daten zeigen kann, muss
POINTER(c_char)verwendet werden. Der Konstruktor akzeptiert eine Ganzzahladresse oder ein Bytes-Objekt.
- class ctypes.c_double¶
Stellt den C-Datentyp double dar. Der Konstruktor akzeptiert einen optionalen Float-Initialisierer.
- class ctypes.c_longdouble¶
Stellt den C-Datentyp long double dar. Der Konstruktor akzeptiert einen optionalen Float-Initialisierer. Auf Plattformen, auf denen
sizeof(long double) == sizeof(double)ist, ist er ein Alias fürc_double.
- class ctypes.c_float¶
Stellt den C-Datentyp float dar. Der Konstruktor akzeptiert einen optionalen Float-Initialisierer.
- class ctypes.c_double_complex¶
Stellt den C-Datentyp double complex dar, falls verfügbar. Der Konstruktor akzeptiert einen optionalen
complex-Initialisierer.Hinzugefügt in Version 3.14.
- class ctypes.c_float_complex¶
Stellt den C-Datentyp float complex dar, falls verfügbar. Der Konstruktor akzeptiert einen optionalen
complex-Initialisierer.Hinzugefügt in Version 3.14.
- class ctypes.c_longdouble_complex¶
Stellt den C-Datentyp long double complex dar, falls verfügbar. Der Konstruktor akzeptiert einen optionalen
complex-Initialisierer.Hinzugefügt in Version 3.14.
- class ctypes.c_int¶
Stellt den C-Datentyp signed int dar. Der Konstruktor akzeptiert einen optionalen Ganzzahl-Initialisierer; es wird keine Überlaufprüfung durchgeführt. Auf Plattformen, auf denen
sizeof(int) == sizeof(long)ist, ist er ein Alias fürc_long.
- class ctypes.c_int16¶
Stellt den C 16-Bit-Datentyp signed int dar. Normalerweise ein Alias für
c_short.
- class ctypes.c_int32¶
Stellt den C 32-Bit-Datentyp signed int dar. Normalerweise ein Alias für
c_int.
- class ctypes.c_int64¶
Stellt den C 64-Bit-Datentyp signed int dar. Normalerweise ein Alias für
c_longlong.
- class ctypes.c_long¶
Stellt den C-Datentyp signed long dar. Der Konstruktor akzeptiert einen optionalen Ganzzahl-Initialisierer; es wird keine Überlaufprüfung durchgeführt.
- class ctypes.c_longlong¶
Stellt den C-Datentyp signed long long dar. Der Konstruktor akzeptiert einen optionalen Ganzzahl-Initialisierer; es wird keine Überlaufprüfung durchgeführt.
- class ctypes.c_short¶
Stellt den C-Datentyp signed short dar. Der Konstruktor akzeptiert einen optionalen Ganzzahl-Initialisierer; es wird keine Überlaufprüfung durchgeführt.
- class ctypes.c_size_t¶
Stellt den C-Datentyp
size_tdar.
- class ctypes.c_ssize_t¶
Stellt den C-Datentyp
ssize_tdar.Hinzugefügt in Version 3.2.
- class ctypes.c_time_t¶
Stellt den C-Datentyp
time_tdar.Hinzugefügt in Version 3.12.
- class ctypes.c_ubyte¶
Stellt den C-Datentyp unsigned char dar und interpretiert den Wert als kleine Ganzzahl. Der Konstruktor akzeptiert einen optionalen Ganzzahl-Initialisierer; es wird keine Überlaufprüfung durchgeführt.
- class ctypes.c_uint¶
Stellt den C-Datentyp unsigned int dar. Der Konstruktor akzeptiert einen optionalen Ganzzahl-Initialisierer; es wird keine Überlaufprüfung durchgeführt. Auf Plattformen, auf denen
sizeof(int) == sizeof(long)ist, ist er ein Alias fürc_ulong.
- class ctypes.c_uint16¶
Stellt den C 16-Bit-Datentyp unsigned int dar. Normalerweise ein Alias für
c_ushort.
- class ctypes.c_uint32¶
Stellt den C 32-Bit-Datentyp unsigned int dar. Normalerweise ein Alias für
c_uint.
- class ctypes.c_uint64¶
Stellt den C 64-Bit-Datentyp unsigned int dar. Normalerweise ein Alias für
c_ulonglong.
- class ctypes.c_ulong¶
Stellt den C-Datentyp unsigned long dar. Der Konstruktor akzeptiert einen optionalen Ganzzahl-Initialisierer; es wird keine Überlaufprüfung durchgeführt.
- class ctypes.c_ulonglong¶
Stellt den C-Datentyp unsigned long long dar. Der Konstruktor akzeptiert einen optionalen Ganzzahl-Initialisierer; es wird keine Überlaufprüfung durchgeführt.
- class ctypes.c_ushort¶
Stellt den C-Datentyp unsigned short dar. Der Konstruktor akzeptiert einen optionalen Ganzzahl-Initialisierer; es wird keine Überlaufprüfung durchgeführt.
- class ctypes.c_void_p¶
Stellt den C-Typ void* dar. Der Wert wird als Ganzzahl repräsentiert. Der Konstruktor akzeptiert einen optionalen Ganzzahl-Initialisierer.
- class ctypes.c_wchar¶
Stellt den C-Datentyp
wchar_tdar und interpretiert den Wert als Unicode-String mit einem einzelnen Zeichen. Der Konstruktor akzeptiert einen optionalen String-Initialisierer; die Länge des Strings muss genau ein Zeichen betragen.
- class ctypes.c_wchar_p¶
Stellt den C-Datentyp wchar_t* dar, der ein Zeiger auf einen nullterminierten Wide-Character-String sein muss. Der Konstruktor akzeptiert eine Ganzzahladresse oder einen String.
- class ctypes.c_bool¶
Stellt den C-Datentyp bool dar (genauer gesagt _Bool aus C99). Sein Wert kann
TrueoderFalsesein, und der Konstruktor akzeptiert jedes Objekt, das einen Wahrheitswert hat.
- class ctypes.HRESULT¶
Stellt einen
HRESULT-Wert dar, der Erfolgs- oder Fehlerinformationen für einen Funktions- oder Methodenaufruf enthält.Verfügbarkeit: Windows
- class ctypes.py_object¶
Stellt den C-Datentyp PyObject* dar. Das Aufrufen ohne Argument erstellt einen
NULLPyObject*-Zeiger.Geändert in Version 3.14:
py_objectist jetzt ein generischer Typ.
Das Modul ctypes.wintypes bietet einige weitere Windows-spezifische Datentypen, z. B. HWND, WPARAM oder DWORD. Einige nützliche Strukturen wie MSG oder RECT sind ebenfalls definiert.
Strukturierte Datentypen¶
- class ctypes.Union(*args, **kw)¶
Abstrakte Basisklasse für Unions in nativer Byte-Reihenfolge.
Unions teilen gemeinsame Attribute und Verhalten mit Strukturen; siehe Dokumentation von
Structurefür Details.
- class ctypes.BigEndianUnion(*args, **kw)¶
Abstrakte Basisklasse für Unions in *Big-Endian*-Byte-Reihenfolge.
Hinzugefügt in Version 3.11.
- class ctypes.LittleEndianUnion(*args, **kw)¶
Abstrakte Basisklasse für Unions in *Little-Endian*-Byte-Reihenfolge.
Hinzugefügt in Version 3.11.
- class ctypes.BigEndianStructure(*args, **kw)¶
Abstrakte Basisklasse für Strukturen in *Big-Endian*-Byte-Reihenfolge.
- class ctypes.LittleEndianStructure(*args, **kw)¶
Abstrakte Basisklasse für Strukturen in *Little-Endian*-Byte-Reihenfolge.
Strukturen und Unions mit nicht-nativer Byte-Reihenfolge können keine Zeigertyp-Felder oder andere Datentypen enthalten, die Zeigertyp-Felder enthalten.
- class ctypes.Structure(*args, **kw)¶
Abstrakte Basisklasse für Strukturen in *nativer* Byte-Reihenfolge.
Konkrete Struktur- und Union-Typen müssen durch Unterklassenbildung einer dieser Typen erstellt werden, und es muss mindestens eine Klassenvariable
_fields_definiert werden.ctypeserstellt Deskriptoren, die das Lesen und Schreiben der Felder durch direkten Attributzugriff ermöglichen. Dies sind die- _fields_¶
Eine Sequenz, die die Felder der Struktur definiert. Die Elemente müssen 2-Tupel oder 3-Tupel sein. Das erste Element ist der Name des Feldes, das zweite Element gibt den Typ des Feldes an; es kann jeder ctypes-Datentyp sein.
Für Ganzzahltyp-Felder wie
c_intkann ein drittes optionales Element angegeben werden. Es muss eine kleine positive Ganzzahl sein, die die Bitbreite des Feldes definiert.Feldnamen müssen innerhalb einer Struktur oder Union eindeutig sein. Dies wird nicht überprüft; bei wiederholten Namen kann nur ein Feld zugegriffen werden.
Es ist möglich, die Klassenvariable
_fields_*nach* der Klassendefinition der Struktur-Unterklasse zu definieren. Dies ermöglicht die Erstellung von Datentypen, die sich direkt oder indirekt auf sich selbst beziehen.class List(Structure): pass List._fields_ = [("pnext", POINTER(List)), ... ]
Die Klassenvariable
_fields_kann nur einmal zugewiesen werden. Spätere Zuweisungen führen zu einemAttributeError.Zusätzlich muss die Klassenvariable
_fields_vor der ersten Verwendung des Struktur- oder Union-Typs definiert werden: eine Instanz oder Unterklasse wird erstellt,sizeof()darauf aufgerufen wird, usw. Spätere Zuweisungen zu_fields_lösen einenAttributeErroraus. Wenn_fields_vor einer solchen Verwendung nicht gesetzt wurde, hat die Struktur oder Union keine eigenen Felder, als ob_fields_leer wäre.Unter-Unterklassen von Strukturtypen erben die Felder der Basisklasse zuzüglich der in der Unter-Unterklasse definierten
_fields_, falls vorhanden.
- _pack_¶
Eine optionale kleine Ganzzahl, die die Ausrichtung von Strukturfeldern in der Instanz überschreiben kann.
Dies ist nur für das MSVC-kompatible Speicherlayout implementiert (siehe
_layout_).Das Setzen von
_pack_auf 0 ist dasselbe wie das Nicht-Setzen. Andernfalls muss der Wert eine positive Zweierpotenz sein. Die Auswirkung ist äquivalent zu#pragma pack(N)in C, außer dassctypesmöglicherweise größere *n* zulässt, als der Compiler akzeptiert._pack_muss bereits definiert sein, wenn_fields_zugewiesen wird, andernfalls hat es keine Auswirkung.Seit Version 3.14 veraltet, wird in Version 3.19 entfernt: Aus historischen Gründen wird das MSVC-kompatible Layout standardmäßig verwendet, wenn
_pack_ungleich Null ist. Auf Nicht-Windows-Plattformen ist dieser Standard veraltet und wird in Python 3.19 zu einem Fehler. Wenn dies beabsichtigt ist, setzen Sie_layout_explizit auf'ms'.
- _align_¶
Eine optionale kleine Ganzzahl, die die Ausrichtung der Struktur beim Packen oder Entpacken von/in Speicher erhöht.
Der Wert darf nicht negativ sein. Die Wirkung ist äquivalent zu
__attribute__((aligned(N)))auf GCC oder#pragma align(N)auf MSVC, mit der Ausnahme, dassctypesmöglicherweise Werte zulässt, die der Compiler ablehnen würde._align_kann die Ausrichtungsanforderungen einer Struktur nur *erhöhen*. Ein Wert von 0 oder 1 hat keine Auswirkung.Die Verwendung von Werten, die keine Zweierpotenzen sind, wird nicht empfohlen und kann zu überraschenden Ergebnissen führen.
_align_muss bereits definiert sein, wenn_fields_zugewiesen wird, andernfalls hat dies keine Auswirkung.Hinzugefügt in Version 3.13.
- _layout_¶
Ein optionaler String, der das Layout von Struktur/Union benennt. Er kann derzeit gesetzt werden auf
"ms": das Layout, das vom Microsoft-Compiler (MSVC) verwendet wird. Auf GCC und Clang kann dieses Layout mit__attribute__((ms_struct))ausgewählt werden."gcc-sysv": das Layout, das von GCC mit dem System V oder „SysV-ähnlichen“ Datenmodell verwendet wird, wie es unter Linux und macOS verwendet wird. Mit diesem Layout muss_pack_nicht gesetzt oder Null sein.
Wenn nicht explizit gesetzt, verwendet
ctypeseinen Standardwert, der den Konventionen der Plattform entspricht. Dieser Standardwert kann sich in zukünftigen Python-Versionen ändern (z. B. wenn eine neue Plattform offiziellen Support erhält oder wenn ein Unterschied zwischen ähnlichen Plattformen festgestellt wird). Derzeit ist der Standardwert:Unter Windows:
"ms"Wenn
_pack_angegeben ist:"ms". (Dies ist veraltet; siehe Dokumentation zu_pack_.)Andernfalls:
"gcc-sysv"
_layout_muss bereits definiert sein, wenn_fields_zugewiesen wird, andernfalls hat dies keine Auswirkung.Hinzugefügt in Version 3.14.
- _anonymous_¶
Eine optionale Sequenz, die die Namen von unbenannten (anonymen) Feldern auflistet.
_anonymous_muss bereits definiert sein, wenn_fields_zugewiesen wird, andernfalls hat dies keine Auswirkung.Die in dieser Variablen aufgeführten Felder müssen Felder vom Typ Struktur oder Union sein.
ctypeserstellt Deskriptoren im Strukturtyp, die den direkten Zugriff auf die verschachtelten Felder ermöglichen, ohne dass die Struktur oder das Union-Feld erstellt werden muss.Hier ist ein Beispieltyp (Windows)
class _U(Union): _fields_ = [("lptdesc", POINTER(TYPEDESC)), ("lpadesc", POINTER(ARRAYDESC)), ("hreftype", HREFTYPE)] class TYPEDESC(Structure): _anonymous_ = ("u",) _fields_ = [("u", _U), ("vt", VARTYPE)]
Die Struktur
TYPEDESCbeschreibt einen COM-Datentyp, das Feldvtgibt an, welches der Union-Felder gültig ist. Da das Felduals anonymes Feld definiert ist, ist es nun möglich, direkt auf die Member der TYPEDESC-Instanz zuzugreifen.td.lptdescundtd.u.lptdescsind äquivalent, aber ersteres ist schneller, da keine temporäre Union-Instanz erstellt werden muss.td = TYPEDESC() td.vt = VT_PTR td.lptdesc = POINTER(some_type) td.u.lptdesc = POINTER(some_type)
Es ist möglich, Unterklassen von Strukturen zu definieren, diese erben die Felder der Basisklasse. Wenn die Unterklassendefinition eine separate Variable
_fields_hat, werden die darin angegebenen Felder an die Felder der Basisklasse angehängt.Struktur- und Union-Konstruktoren akzeptieren sowohl Positions- als auch Schlüsselwortargumente. Positionsargumente werden verwendet, um Mitgliedsfelder in derselben Reihenfolge zu initialisieren, in der sie in
_fields_erscheinen. Schlüsselwortargumente im Konstruktor werden als Attributzuweisungen interpretiert, sodass sie_fields_mit demselben Namen initialisieren oder neue Attribute für Namen erstellen, die nicht in_fields_vorhanden sind.
- class ctypes.CField(*args, **kw)¶
Deskriptor für Felder einer
StructureundUnion. Zum Beispiel>>> class Color(Structure): ... _fields_ = ( ... ('red', c_uint8), ... ('green', c_uint8), ... ('blue', c_uint8), ... ('intense', c_bool, 1), ... ('blinking', c_bool, 1), ... ) ... >>> Color.red <ctypes.CField 'red' type=c_ubyte, ofs=0, size=1> >>> Color.green.type <class 'ctypes.c_ubyte'> >>> Color.blue.byte_offset 2 >>> Color.intense <ctypes.CField 'intense' type=c_bool, ofs=3, bit_size=1, bit_offset=0> >>> Color.blinking.bit_offset 1
Alle Attribute sind schreibgeschützt.
CFieldObjekte werden über_fields_erstellt; instanziieren Sie die Klasse nicht direkt.Hinzugefügt in Version 3.14: Zuvor hatten Deskriptoren nur Attribute
offsetundsizeund eine lesbare Zeichenkettenrepräsentation; die KlasseCFieldwar nicht direkt verfügbar.- name¶
Name des Feldes, als Zeichenkette.
- type¶
Typ des Feldes, als ctypes-Klasse.
- offset¶
- byte_offset¶
Offset des Feldes in Bytes.
Bei Bitfeldern ist dies der Offset der zugrundeliegenden Byte-ausgerichteten *Speichereinheit*; siehe
bit_offset.
- byte_size¶
Größe des Feldes in Bytes.
Bei Bitfeldern ist dies die Größe der zugrundeliegenden *Speichereinheit*. Typischerweise hat sie die gleiche Größe wie der Typ des Bitfeldes.
- size¶
Für Nicht-Bitfelder äquivalent zu
byte_size.Für Bitfelder enthält dies einen abwärtskompatiblen, bitgepackten Wert, der
bit_sizeundbit_offsetkombiniert. Es ist vorzuziehen, die expliziten Attribute zu verwenden.
- is_bitfield¶
True, wenn dies ein Bitfeld ist.
- bit_offset¶
- bit_size¶
Die Position eines Bitfeldes innerhalb seiner *Speichereinheit*, d.h. innerhalb von
byte_sizeBytes Speicher, beginnend beibyte_offset.Um den Wert des Feldes zu erhalten, lesen Sie die Speichereinheit als Ganzzahl, verschieben Sie sie nach links um
bit_offsetund nehmen Sie diebit_sizeniedrigstwertigen Bits.Für Nicht-Bitfelder ist
bit_offsetNull undbit_sizeist gleichbyte_size * 8.
- is_anonymous¶
True, wenn dieses Feld anonym ist, d.h. es enthält verschachtelte Unterfelder, die in eine enthaltende Struktur oder Union zusammengeführt werden sollten.
Arrays und Zeiger¶
- class ctypes.Array(*args)¶
Abstrakte Basisklasse für Arrays.
Der empfohlene Weg zur Erstellung konkreter Array-Typen ist die Multiplikation eines beliebigen
ctypes-Datentyps mit einer nicht-negativen Ganzzahl. Alternativ können Sie diese Klasse unterklassifizieren und die Klassenvariablen_length_und_type_definieren. Array-Elemente können über standardmäßige Subskript- und Slice-Zugriffe gelesen und geschrieben werden; für Slice-Lesevorgänge ist das resultierende Objekt *nicht* selbst einArray.- _length_¶
Eine positive Ganzzahl, die die Anzahl der Elemente im Array angibt. Außerhalb des Bereichs liegende Indizes führen zu einem
IndexError. Wird vonlen()zurückgegeben.
- _type_¶
Gibt den Typ jedes Elements im Array an.
Array-Unterklassen-Konstruktoren akzeptieren Positionsargumente, die zur Initialisierung der Elemente in der Reihenfolge verwendet werden.
- ctypes.ARRAY(type, length)¶
Erstellt ein Array. Äquivalent zu
type * length, wobei *type* einctypes-Datentyp und *length* eine Ganzzahl ist.Diese Funktion ist zugunsten der Multiplikation soft deprecated. Es gibt keine Pläne, sie zu entfernen.
- class ctypes._Pointer¶
Private, abstrakte Basisklasse für Zeiger.
Konkrete Zeigertypen werden durch Aufruf von
POINTER()mit dem Typ, auf den gezeigt wird, erstellt; dies geschieht automatisch durchpointer().Wenn ein Zeiger auf ein Array zeigt, können dessen Elemente über standardmäßige Subskript- und Slice-Zugriffe gelesen und geschrieben werden. Zeigerobjekte haben keine Größe, daher löst
len()einenTypeErroraus. Negative Indizes lesen aus dem Speicher *vor* dem Zeiger (wie in C), und außerhalb des Bereichs liegende Indizes führen wahrscheinlich zu einem Absturz mit Zugriffsverletzung (wenn Sie Glück haben).- _type_¶
Gibt den Typ an, auf den gezeigt wird.
- contents¶
Gibt das Objekt zurück, auf das der Zeiger zeigt. Eine Zuweisung zu diesem Attribut ändert den Zeiger, sodass er auf das zugewiesene Objekt zeigt.
Ausnahmen¶
- exception ctypes.ArgumentError¶
Diese Ausnahme wird ausgelöst, wenn ein Aufruf einer fremden Funktion eines der übergebenen Argumente nicht konvertieren kann.
- exception ctypes.COMError(hresult, text, details)¶
Diese Ausnahme wird ausgelöst, wenn ein COM-Methodenaufruf fehlschlägt.
- hresult¶
Der ganzzahlige Wert, der den Fehlercode darstellt.
- text¶
Die Fehlermeldung.
- details¶
Das 5-Tupel
(descr, source, helpfile, helpcontext, progid).descr ist die textuelle Beschreibung. source ist die sprachabhängige
ProgIDfür die Klasse oder Anwendung, die den Fehler ausgelöst hat. helpfile ist der Pfad zur Hilfedatei. helpcontext ist die ID des Hilfe-Kontextes. progid ist dieProgIDder Schnittstelle, die den Fehler definiert hat.
Verfügbarkeit: Windows
Hinzugefügt in Version 3.14.