Seite 1 von 1

python mit C erweitern

Verfasst: Samstag 23. Januar 2010, 13:26
von buggy
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

Verfasst: Samstag 23. Januar 2010, 14:42
von theliquidwave
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

Verfasst: Samstag 23. Januar 2010, 20:25
von str1442
PyList_GetItem() ist die Implementation für das allgemeine __getitem__(), die append() Methode heißt PyList_Append().

Verfasst: Samstag 23. Januar 2010, 22:22
von buggy
Danke, kann man irgendwie erfahren, welcher Datentyp in dem PytObject drin steckt?

Verfasst: Samstag 23. Januar 2010, 23:22
von BlackJack
Kann man. Warum möchtest Du das denn?

Verfasst: Sonntag 24. Januar 2010, 12:43
von buggy
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.

Verfasst: Montag 25. Januar 2010, 10:50
von Masaru
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<<

Verfasst: Montag 25. Januar 2010, 18:18
von buggy
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:

Verfasst: Montag 25. Januar 2010, 20:14
von derdon
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

Verfasst: Dienstag 26. Januar 2010, 15:12
von Masaru
Ah, jap, definitiv :). Schön wieder was dazu gelernt zu haben.

Verfasst: Dienstag 26. Januar 2010, 15:47
von 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.

Verfasst: Samstag 30. Januar 2010, 22:23
von str1442
@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)

Verfasst: Samstag 30. Januar 2010, 22:28
von DasIch

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...

Verfasst: Samstag 30. Januar 2010, 22:39
von str1442
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.

Verfasst: Sonntag 31. Januar 2010, 10:22
von 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)

Verfasst: Sonntag 31. Januar 2010, 21:05
von str1442
Stimmt, das hatte ich nicht beachtet, danke! :idea: