C-Programme in Python einbinden

Code-Stücke können hier veröffentlicht werden.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Hi!

Es ist immer wieder erstaunlich, wie einfach manche Dinge mit Python sein können. :wink:

Im iX-Magazin 12/2006 (Seite 84) habe ich folgende Codesnippets gefunden. Diese Codeteile demonstrieren, wie man ein kleines C-Programm in Python einbinden kann, um z.B. die Geschwindigkeit des Python-Programmes, gezielt an rechenintensiven Stellen, zu erhöhen.

fib.c:

Code: Alles auswählen

// Das C-Programm
int fib(int n) {
  if(n > 2) 
    return fib(n - 1) + fib(n - 2);
  else 
    return 1;
}
fibfast.py:

Code: Alles auswählen

#!/usr/bin/env python
import ctypes
f = ctypes.cdll.LoadLibrary("fib.so")
print f.fib(35)
startfib.sh:

Code: Alles auswählen

#!/bin/bash
cc -c fib.c
cc -shared fib.o -o fib.so
LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:. python fibfast.py
Ich habe dieses Beispiel mit Cygwin ausprobiert. Ctypes habe ich mir dafür hier besorgt und mit ``python setup.py install`` unter Cygwin installiert.

lg
Gerold
:-)
Zuletzt geändert von gerold am Sonntag 12. November 2006, 22:28, insgesamt 1-mal geändert.
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Super! Vielen Dank für die Info!
Christian
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Danke auch. Dass es so einfach und ohne SWIG o.ä. geht, wusste ich nicht.

ctypes wird übrigens ab Python 2.5 mitgeliefert.
Benutzeravatar
birkenfeld
Python-Forum Veteran
Beiträge: 1603
Registriert: Montag 20. März 2006, 15:29
Wohnort: Die aufstrebende Universitätsstadt bei München

Nun, so einfach geht es halt nur, wenn im C-Code keine Python-Objekte manipuliert werden sollen. Dann kommt man um die Python-API nicht herum (was aber nicht heißt, dass es dann wesentlich komplizierter wird).
BlackJack

Wenn auf der C-Seite Python-Objekte manipuliert werden sollen, dann würde ich zuallererst schauen ob Pyrex ausreicht.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Der Tipp würde mit MinGW warscheinlich sehr ähnlich gehen, nur würde der Compiler dann vermutlich eine DLL generieren, die natürlich genauso wie die SO-Library durch ctypes angesprochen werden könnte.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

@gerold: Danke für das Beispiel. Werde ich bei Zeit mal ausprobieren.

lg
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Wäre mal wieder was für das Wiki! *vote*

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

jens hat geschrieben:Wäre mal wieder was für das Wiki! *vote*
*zustimm!*
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Hi!

Weil es so schön ins Thema passt.

Mit Elmer http://wiki.python.org/moin/elmer lässt sich Python-Code in C, C++ und Tcl einbinden.

Allerdings habe ich das nicht getestet. Falls jemand Elmer testen würde und hier das Ergebnis des Tests posten könnte... das wäre eine super Sache. :-)

lg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

XtraNine hat geschrieben:
jens hat geschrieben:Wäre mal wieder was für das Wiki! *vote*
*zustimm!*
Abstimmungen bringen da nichts: Da ist Handanlegen gefragt, it's a wiki (bzw. Bezahlung von Dokumentationsschreibern).
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Hi!

Nachdem ich wie in http://www.python-forum.de/topic-7855.html beschrieben, MinGW installiert hatte, musste ich natürlich auch ausprobieren ob dieses Beispiel so auch mit MinGW funktioniert. 8)

fib.c:

Code: Alles auswählen

// Das C-Programm
int fib(int n) {
  if(n > 2) 
    return fib(n - 1) + fib(n - 2);
  else 
    return 1;
}
fibfast.py:

Code: Alles auswählen

#!/usr/bin/env python
import ctypes
f = ctypes.cdll.LoadLibrary("fib.dll")
print f.fib(35)
startfib.cmd:

Code: Alles auswählen

gcc -c fib.c
gcc -shared fib.o -o fib.dll
REM LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:. python 
python fibfast.py
pause
Natürlich funktioniert es!

Viel Vergnügen beim "Selberausprobieren". :D

lg
Gerold
:-)
Edit: fib.so --> fib.dll
Zuletzt geändert von gerold am Donnerstag 16. November 2006, 23:32, insgesamt 1-mal geändert.
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Vermutlich wäre es schlauer, an dieser Stelle fib.so durch fib.dll zu ersetzen, denn die fib.so ist durchaus eine funktionsfähige Win32-DLL.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Leonidas hat geschrieben:die fib.so ist durchaus eine funktionsfähige Win32-DLL.
Hi Leonidas!

Ich hab's geändert.

lg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Und so geht's unter Windows mit Open Watcom:

Code: Alles auswählen

#include <windows.h>

int FAR PASCAL __export fib(int n)
{
  if(n > 2)
    return fib(n - 1) + fib(n - 2);
  else
    return 1;
}

Code: Alles auswählen

#!/usr/local/bin/python
# File: fibfast.py
import ctypes
f = ctypes.WinDLL('fib')
print f.fib(35)
MfG
HWK
BlackJack

``PASCAL``!? Das ``FAR`` könnte ich ja noch verstehen wenn der OpenWatcom sonst 16-Bit-Code generiert, aber der Unterschied zwischen Aufrufen in Pascal und C ist doch die Reihenfolge in der die Argumente auf dem Stack abgelegt werden und wer für's Aufräumen des Stacks zuständig ist. Und da dachte ich das DLLs der C-Konvention folgen!?
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Das FAR kann man wirklich bei der 32-Bit-Code-Voreinstellung weglassen. Wenn ich aber statt PASCAL gar nichts oder CDECL angebe, wird die Funktion fib unter dem Namen fib_ oder _fib exportiert, was natürlich unschön ist. Wenn ich PASCAL angebe, muss ich entsprechend in ctypes auch WinDLL verwenden.
MfG
HWK
BlackJack

Wo kommt der Unterstrich denn her? Und warum? Kann das am ``__extern`` liegen? Was macht das denn? Normalerweise wird bei C doch jede Funktion die nicht ``static`` deklariert wurde auch automatisch unter ihrem Namen wie er im Quelltext steht in der object-Datei verfügbar gemacht. So kenne ich das jedenfalls von allen C-Compilern mit denen ich bis jetzt zu tun hatte.
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Weiss ich auch nicht genau. Auf jeden Fall sind __export (nicht __extern) oder __declspec(dllexport) notwendig, damit etwas aus der DLL exportiert wird. Dies ist auch bei Visual-C der Fall. Möglicherweise sind es C-Konventionen unter Windows, dass eine exportierte Funktion mit einem Unterstrich beginnt oder endet, denn bei PASCAL passiert dies ja nicht. Deshalb sollte es am __export nicht liegen.
MfG
HWK
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

HWK hat geschrieben:Weiss ich auch nicht genau. Auf jeden Fall sind __export (nicht __extern) oder __declspec(dllexport) notwendig, damit etwas aus der DLL exportiert wird. Dies ist auch bei Visual-C der Fall. [...]
Full ack! Nicht nur bei VC sondern auch mit gcc unter Windows. Wie das unter Linux aussieht weiß ich auch nicht.
Antworten