python mit C erweitern

Python in C/C++ embedden, C-Module, ctypes, Cython, SWIG, SIP etc sind hier richtig.
Antworten
buggy
User
Beiträge: 4
Registriert: Samstag 23. Januar 2010, 00:08

Hi,
ich versuche gerade ein geschriebenes Programm in C in python einzubinden.

Ich benutze dafür die Python API für C.

Leider weiß ich nicht, wie man Datenstrukturen wie Listen oder Tupel von Python in C bekommt.

Einzelne Datentypen wie Integer, sind kein Problem, nur ich brauche halt die Liste aus Python in meinem C code ;-)

Gruß
buggy
theliquidwave
User
Beiträge: 221
Registriert: Sonntag 1. Juni 2008, 09:08

Hi.
Das ist eigentlich ganz einfach.
Jedes Objekt in Python ist in C vom Typ "PyObject *". Du kannst jeden Typen erstellen, z.B. mit PyString_New();.
So kannst du das auch einfach mit Listen machen:

Code: Alles auswählen

PyObject *pList = PyList_New();
PyList_AddItem(PyString_New("test")); // keine Ahnung ob die Funktion wirklich so heißt, PyList_GetItem gibt es jedenfalls
Chris
Grüßle.
Benutzeravatar
str1442
User
Beiträge: 520
Registriert: Samstag 31. Mai 2008, 21:13

PyList_GetItem() ist die Implementation für das allgemeine __getitem__(), die append() Methode heißt PyList_Append().
buggy
User
Beiträge: 4
Registriert: Samstag 23. Januar 2010, 00:08

Danke, kann man irgendwie erfahren, welcher Datentyp in dem PytObject drin steckt?
BlackJack

Kann man. Warum möchtest Du das denn?
buggy
User
Beiträge: 4
Registriert: Samstag 23. Januar 2010, 00:08

Ich möchte aus der Python liste, ein double array erstellen.
Da man in Python alle Objekte in einer Liste speichern kann, kann es sein, dass irgendein Datentyp in der Liste steht.

Um jetzt falsche ergebnisse auszuschließen, würde ich gerne überprüfen ob in der Liste auch eine Zahl drin steht.
Benutzeravatar
Masaru
User
Beiträge: 425
Registriert: Mittwoch 4. August 2004, 22:17

Naja, ist ja nicht so das Problem oder?

Code: Alles auswählen

>>> clear_float_list = [ 0.5, 0.6, 1.0 ]
>>> mixed_list = [ 0.5, "This is a test", { 'key' : True } ]

>>> assert [ isinstance(e, float) for e in clear_float_list ].count(False) == 0
# kein Fehler
>>> assert [ isinstance(e, float) for e in mixed_list ].count(False) == 0
Traceback (most recent call last):
  File "<interactive input>", line 1, in <module>
AssertionError
>>Masaru<<
buggy
User
Beiträge: 4
Registriert: Samstag 23. Januar 2010, 00:08

Danke.

Ich hätte dies eher in C gemacht, denn falls eine Integer vor kommt, hätte ich es auch als double casten können. Aber so gehts auch :wink:
derdon
User
Beiträge: 1316
Registriert: Freitag 24. Oktober 2008, 14:32

Masaru: Da bietet sich doch all an:

Code: Alles auswählen

>>> clear_float_list = [ 0.5, 0.6, 1.0 ]
>>> mixed_list = [ 0.5, "This is a test", { 'key' : True } ]
>>> assert all(isinstance(e, float) for e in clear_float_list)
>>> assert all(isinstance(e, float) for e in mixed_list)
Traceback (most recent call last):
  File "<input>", line 1, in <module>
AssertionError
Benutzeravatar
Masaru
User
Beiträge: 425
Registriert: Mittwoch 4. August 2004, 22:17

Ah, jap, definitiv :). Schön wieder was dazu gelernt zu haben.
BlackJack

Alles schön und gut, aber meine Frage bleibt immer noch bei dem warum!? Man könnte auch einfach in C davon ausgehen, dass das was man da hat ein "iterable" ist, durch die ganzen Elemente gehen und sich ein `double()` davon geben lassen. Falls das nicht geht, eben entsprechend den Fehler als Ausnahme weitermelden. Wie man das in Python halt auch machen würde.

Oder man verwendet `ctypes` zur Kommunikation mit dem C-Teil.
Benutzeravatar
str1442
User
Beiträge: 520
Registriert: Samstag 31. Mai 2008, 21:13

@Masaru, nur der Vollständigkeit halber:

Code: Alles auswählen

from functools import reduce, partial
all = partial(reduce, lambda a, b: a and b)
any = partial(reduce, lambda a, b: a or b)
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Code: Alles auswählen

>>> all([])
True
>>> all([1])
True
>>> from functools import partial
>>> all = partial(reduce, lambda a, b: a and b)
>>> all([])
Traceback (most recent call last):
  File "<input>", line 1, in <module>
TypeError: reduce() of empty sequence with no initial value
>>> all([1])
1
Hm...
Benutzeravatar
str1442
User
Beiträge: 520
Registriert: Samstag 31. Mai 2008, 21:13

Ok :):

Code: Alles auswählen

>>> def all(x):
...  return reduce(lambda a, b: a and b, x, True)
... 
>>> all([])
True
>>> all([1])
1
>>> all([1, 2])
2
>>> # Mit expliziter Umwandlung nach bool wie bei all()
... 
>>> def all(x):
...  return reduce(lambda a, b: a and bool(b), x, True)
... 
>>> all([])
True
>>> all([1])
True
>>> all([1, 4])
True
Leider funktioniert partial() hier nicht mehr, da reduce() wie eine Reihe von anderen Builtin Funktionen keine Keywordargumente annimmt.
BlackJack

@str1442: `reduce()` taugt hier nicht weil das tatsächlich *alles* auswertet. `any()` und `all()` brechen aber ab, sobald das Ergebnis feststeht.

Code: Alles auswählen

def all(iterable):
    return False not in imap(bool, iterable)

def any(iterable):
    return True in imap(bool, iterable)
Benutzeravatar
str1442
User
Beiträge: 520
Registriert: Samstag 31. Mai 2008, 21:13

Stimmt, das hatte ich nicht beachtet, danke! :idea:
Antworten