2010-08-10 4 views
5

Ich versuche, das Python "Ctypes" -Modul zu verstehen. Ich habe ein triviales Beispiel zusammengestellt, das im Idealfall den Funktionsaufruf statvfs() umschließt. Der Code sieht wie folgt aus:Helfen Sie mir zu verstehen, warum meine triviale Verwendung von Pythons Ctypes-Modul fehlschlägt

from ctypes import * 

class struct_statvfs (Structure): 
    _fields_ = [ 
      ('f_bsize', c_ulong), 
      ('f_frsize', c_ulong), 
      ('f_blocks', c_ulong), 
      ('f_bfree', c_ulong), 
      ('f_bavail', c_ulong), 
      ('f_files', c_ulong), 
      ('f_ffree', c_ulong), 
      ('f_favail', c_ulong), 
      ('f_fsid', c_ulong), 
      ('f_flag', c_ulong), 
      ('f_namemax', c_ulong), 
      ] 


libc = CDLL('libc.so.6') 
libc.statvfs.argtypes = [c_char_p, POINTER(struct_statvfs)] 
s = struct_statvfs() 

res = libc.statvfs('/etc', byref(s)) 
print 'return = %d, f_bsize = %d, f_blocks = %d, f_bfree = %d' % (
    res, s.f_bsize, s.f_blocks, s.f_bfree) 

Ausführen dieses immer wieder:

return = 0, f_bsize = 4096, f_blocks = 10079070, f_bfree = 5048834 
*** glibc detected *** python: free(): invalid next size (fast): 0x0000000001e51780 *** 
*** glibc detected *** python: malloc(): memory corruption (fast): 0x0000000001e517e0 *** 

Ich habe nicht in der Lage gewesen, alle Beispiele Aufruf von Funktionen mit komplexen Typen wie Parameter finden (es gibt viele Beispiele von Funktionen, die komplexe Typen zurückgeben, aber nach dem Anschauen der Ctypes-Dokumentation für einen Tag oder so denke ich, dass meine Aufrufsyntax korrekt ist ... und es tatsächlich den statvfs() -Aufruf aufruft und korrekte Ergebnisse zurückbekommt.

Bin ich Missverständnis der Ctypes Docs? Oder geht hier etwas anderes vor?

Danke!

+0

Ich konnte noch keine Antwort finden, aber ich kann Ihnen sagen, dass Ihr Code für mich funktioniert, wenn ich ihn als Skript ausführe, aber es verursacht einen Segfault, wenn ich ihn im interaktiven Interpreter starte. Insbesondere verursacht es einen Segfault nach einer scheinbar zufälligen Zeitspanne oder wenn der Interpreter beendet wird, je nachdem, was zuerst eintritt.Ich werde weiter versuchen, das herauszufinden, aber ich dachte mir, dass diese Information das Problem für jemanden, der besser informiert ist, beleuchten könnte. –

+1

Ein Problem könnte sein, dass Sie die Klasse struct_statvfs nicht richtig definieren müssen, z. Dein ist kleiner als das, was die libc denkt. Führen Sie dieses kleine C-Programm aus, um Folgendes zu überprüfen: #include int main() {return! Printf ("% d \ n", sizeof (struct statvfs)); } – pts

+0

Falsche und veraltete Dokumentation ist schlimmer als keine Dokumentation. Es ist mir nicht in den Sinn gekommen, die Definition für eine Struktur (nicht verwandt mit statvfs) zu betrachten, die mich stört. Gut, dass ich diese Frage gesehen habe. – ianalis

Antwort

4

Führen Sie diesen Befehl aus, um die genaue Definition von struct statvfs auf Ihrem System zu erhalten :

echo '#include <sys/statvfs.h>' | gcc -E - | less 

Drücken Sie dann /struct statvfs<enter> die Definition zu überspringen und von dort zu suchen.

Schauen Sie sich auch my patch zu fusepy, und their definition.

+1

Das ist es, was ich bekomme, wenn ich der Manpage vertraue. Danke für den Vorschlag! Da ich zum ersten Mal mit ctypes arbeite, war ich mir nicht sicher, was genau der Fehler bedeutet. – larsks

+0

coole Abkürzung für die Definition der Struktur. Ich muss mich daran erinnern. – Mark

+0

Ja, Ctypes ist viel geredet, aber es ist immer noch schmerzhaft, alles richtig zu definieren. Es hilft wirklich nicht, dass ein C-Compiler irgendwie notwendig ist. Es sollte einen offiziellen ABI-Standard geben, auf den sich C und andere Sprachen gegenseitig verlassen können. –

2

Die Manpage für statvfs gibt an, dass die verwendete Struktur "ungefähr wie folgt definiert" ist. Sie können also die Feldlisten der Manpage nicht unbedingt als abgeschlossen betrachten.

Meine Vermutung ist, dass es zusätzliche Strukturfelder nach dem Ende der Struktur gibt, wie Sie es definiert haben. Dies bewirkt, dass die Funktion statvfs Speicher außerhalb Ihrer Struktur überschreibt. Ich habe das Problem, gehen weg für mich durch eine riesige Padding-Feld auf die _fields_ in meinem struct Definition hinzufügen:

("padding", c_int * 1000), 

Beachten Sie, dass mein Skript das Problem anders als Ihr manifestiert; Ich habe einen segfault, während Sie nur einige Fehlermeldungen erhalten haben. Trotzdem vermute ich, dass es sich um das gleiche Problem handelt. Daher sollten Sie versuchen, eine Auffüllung hinzuzufügen und zu prüfen, ob das Problem weiterhin besteht.

+1

c_int * 6 scheint genug zu sein (aber * 1000 ist sicherer, * 100 sollte sicher genug sein), siehe /usr/include/bits/statvfs.h unter Linux: struct statvfs enthält int __f_spare [6]; – pts

2

Wie Eli angibt, ist Ihre Struktur in /usr/include/bits/statvfs.h nicht richtig definiert.

Auf meinem 64-Bit-Gentoo-System wäre es:

class struct_statvfs (Structure): 
    _fields_ = [ 
      ('f_bsize', c_ulong), 
      ('f_frsize', c_ulong), 
      ('f_blocks', c_ulong), 
      ('f_bfree', c_ulong), 
      ('f_bavail', c_ulong), 
      ('f_files', c_ulong), 
      ('f_ffree', c_ulong), 
      ('f_favail', c_ulong), 
      ('f_fsid', c_ulong), 
      ('f_flag', c_ulong), 
      ('f_namemax', c_ulong), 
      ('__f_space', c_int * 6) # you are missing this 
      ] 
0

Nach der erfolgreichen pyfuse ctypes Wrapper für Sicherung, wird die folgend für struct statvfs unter Linux verwendet:

class c_statvfs(Structure): 
    _fields_ = [ 
     ('f_bsize', c_ulong), 
     ('f_frsize', c_ulong), 
     ('f_blocks', c_fsblkcnt_t), 
     ('f_bfree', c_fsblkcnt_t), 
     ('f_bavail', c_fsblkcnt_t), 
     ('f_files', c_fsfilcnt_t), 
     ('f_ffree', c_fsfilcnt_t), 
     ('f_favail', c_fsfilcnt_t)] 

Mehr Info: http://code.google.com/p/fusepy/

+1

Vielleicht möchte ich einen Patch zu Fusepy, die ich eingereicht habe, die Korrekturen zu ihren Statvfs enthält. http://code.google.com/p/fusepy/issues/detail?id=26 –

+0

Ahh nett. Habe nicht bemerkt, dass es veraltet war. Übrigens, ich habe bemerkt, dass "Fusepy" nur einen Haken für Statfs hat, nicht Statvfs. –

Verwandte Themen