@ddpf: „Meckert rum” ohne konkrete Fehlermeldung und den dazugehörigen Quelltext ist keine Fehlerbeschreibung bei der man sinnvoll helfen könne. Was hast Du versucht, und was war das Ergebnis? Wenn es keine Fehlermeldung war, wie weicht das Ergebnis vom Erwarteten ab?
Eine Struktur mit nur einem Feld zu erstellen ist jedenfalls einfach und unterscheided sich zum Erstellen von einer mit mehreren Feldern nur dadurch, dass man nur ein Feld statt mehrere definiert. Wer hätte das gedacht.
Also in Deinem Fall einfach:
Code: Alles auswählen
class GEN(Structure):
_fields_ = [('channel_number', CHANNEL * 16)]
Bei entsprechender Definitionen von `CHANNEL`.
Du zeigst ja leider nicht, was Du in *Python* versucht hast, und wo die Probleme dort liegen. Also rate ich mal, dass beim Aufruf von `channel_ctor()` beim ersten Argument nicht nur eine 0 als Index vorkommen kann, denn dann wäre es ja einfach, weil man das Array selbst, beziehungsweise einen Zeiger darauf (was wegen der C-Semantik auf's selbe raus kommt), übergeben könnte.
Um einen Zeiger auf ein Element innerhalb eines Arrays zu bekommen, bietet `ctypes` leider keine vorgefertigte Lösung an. Die Adressarithmetik dafür muss man komplett selbst schreiben. Also Adresse des Arrays plus `i` mal Grösse eines Elements berechnen, dann wieder einen `ctypes`-Proxy für das Element aus dieser neuen Adresse erstellen und darauf dann einen Zeiger an `channel_ctor()` übergeben.
Warum steht im C-Beispielprogramm in den Kommentaren eigentlich, dass der Rückgabewert wichtig ist, aber er wird dann überhaupt nicht verwendet? Zeigt der Rückgabewert Fehler an? Also zum Beispiel 0 bedeutet kein Fehler? Dann solltest Du überlegen eine Funktion an das `errcheck`-Attribut der `ctypes`-Proxy-Objekte für die Funktionen zu binden, die im Fehlerfall eine Ausnahme auslöst.
Edit: Konnte ich natürlich nicht mit Deiner Bibliothek testen, und da Deine Beispiel-`main()` in dem C-Programm nicht unbedingt verrät welche Argumente ”fest” und welche ”variabel” sind und wie die Funktionen semantisch zusammenhängen, weiss ich auch nicht ob die `Gen`-Klasse so vernünftig ist:
Code: Alles auswählen
#!/usr/bin/env python
# coding: utf-8
from ctypes import (
addressof, byref, c_ubyte, c_ushort, cast, CDLL, sizeof, POINTER,
Structure
)
GEN_LIB = CDLL('./libgen.so')
class Error(Exception):
pass
class CHANNEL(Structure):
_fields_ = [
('blah', POINTER(c_ushort)),
('muh', POINTER(c_ushort)),
('type', c_ushort),
('ch_number', c_ubyte),
]
class GEN(Structure):
_fields_ = [('channel_number', CHANNEL * 16)]
CHANNEL_PTR = POINTER(CHANNEL)
GEN_PTR = POINTER(GEN)
def _error_check(result, func, arguments):
if result != 0:
raise Error('%s%r returned %d' % (func, arguments, result))
_ctor = GEN_LIB.ctor
_ctor.argtypes = [GEN_PTR]
_ctor.restype = c_ushort
_ctor.errcheck = _error_check
_channel_ctor = GEN_LIB.channel_ctor
_channel_ctor.argtypes = [CHANNEL_PTR, c_ushort, c_ushort, c_ushort]
_channel_ctor.restype = c_ushort
_channel_ctor.errcheck = _error_check
_copy_data = GEN_LIB.copy_data
_copy_data.argtypes = [POINTER(c_ushort)]
_copy_data.restype = None
_update_all_channels = GEN_LIB.update_all_channels
_update_all_channels.argtypes = []
_update_all_channels.restype = None
class Gen(GEN):
def __init__(self):
GEN.__init__(self)
_ctor(byref(self))
def init_channel(self, i, a, b, c):
_channel_ctor(
byref(
CHANNEL.from_address(
addressof(self.channel_number) + sizeof(CHANNEL) * i
)
),
a,
b,
c
)
def do_something(self):
result = (c_ushort * 16 * 256)()
for row in result:
_copy_data(cast(row, POINTER(c_ushort)))
_update_all_channels()
return result
def main():
gen = Gen()
gen.init_channel(0, 1, 20, 50)
result = gen.do_something()
for row in result:
print list(row)
if __name__ == '__main__':
main()