Seite 1 von 2

C-Programme in Python einbinden

Verfasst: Sonntag 12. November 2006, 22:07
von gerold
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
:-)

Verfasst: Sonntag 12. November 2006, 22:20
von CM
Super! Vielen Dank für die Info!
Christian

Verfasst: Sonntag 12. November 2006, 23:34
von Y0Gi
Danke auch. Dass es so einfach und ohne SWIG o.ä. geht, wusste ich nicht.

ctypes wird übrigens ab Python 2.5 mitgeliefert.

Verfasst: Montag 13. November 2006, 09:13
von birkenfeld
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).

Verfasst: Montag 13. November 2006, 10:44
von BlackJack
Wenn auf der C-Seite Python-Objekte manipuliert werden sollen, dann würde ich zuallererst schauen ob Pyrex ausreicht.

Verfasst: Montag 13. November 2006, 11:11
von Leonidas
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.

Verfasst: Montag 13. November 2006, 22:48
von sape
@gerold: Danke für das Beispiel. Werde ich bei Zeit mal ausprobieren.

lg

Verfasst: Dienstag 14. November 2006, 09:39
von jens
Wäre mal wieder was für das Wiki! *vote*

Verfasst: Dienstag 14. November 2006, 12:47
von sape
jens hat geschrieben:Wäre mal wieder was für das Wiki! *vote*
*zustimm!*

Verfasst: Donnerstag 16. November 2006, 15:52
von gerold
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
:-)

Verfasst: Donnerstag 16. November 2006, 17:45
von Leonidas
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).

Verfasst: Donnerstag 16. November 2006, 23:19
von gerold
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

Verfasst: Donnerstag 16. November 2006, 23:23
von Leonidas
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.

Verfasst: Donnerstag 16. November 2006, 23:33
von gerold
Leonidas hat geschrieben:die fib.so ist durchaus eine funktionsfähige Win32-DLL.
Hi Leonidas!

Ich hab's geändert.

lg
Gerold
:-)

Verfasst: Sonntag 26. November 2006, 15:46
von HWK
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

Verfasst: Sonntag 26. November 2006, 17:03
von 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!?

Verfasst: Sonntag 26. November 2006, 19:17
von HWK
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

Verfasst: Sonntag 26. November 2006, 19:57
von 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.

Verfasst: Sonntag 26. November 2006, 20:25
von HWK
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

Verfasst: Sonntag 26. November 2006, 20:28
von sape
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.