Seite 1 von 1
ctypes Modul kann nicht mehrere DLLs laden
Verfasst: Mittwoch 9. Mai 2012, 19:33
von marvel82
Hallo liebe Community,
ich versuche seit Tagen ein Problem zu lösen, jedoch bisher ohne Erfolg und langsam gehen mir die Alternativen aus

. Ich nutze das ctypes Modul und lade der Reihe nach DLL-Dateien, die ich während der Laufzeit verwenden möchte.
Ich habe via
eine Instanz der Klasse CDLL erzeugt und rufe dann immer cdll.loadlibrary() auf. Die erste DLL die ich übergebe wird ordnungsgemäß geladen und ich kann sie verwenden, jedoch wenn ich die Instanz zerstöre wird die DLL nicht entladen. Sobald ich eine neue Instanz erzeuge und dann wieder cdll.loadlibrary() aufrufe wird wieder die vorherige DLL geladen anstatt die die ich aktuell übergeben habe. Ich habe schon versucht über die win32api für python mit loadlibrary() und freelibrary() das ganze selber zu handlen, aber es funtzt auch nicht. Ich hoffe Ihr habt eine Lösung, sonst ist eine Menge Arbeit für die Katz. Sollte der Sachverhalt nicht ganz klar sein, poste ich gerne noch Quellcode
Vielen Dank im voraus und haltet die Ohren steif
MfG
marvel82
Re: ctypes Modul kann nicht mehrere DLLs laden
Verfasst: Mittwoch 9. Mai 2012, 19:37
von BlackJack
@marvel82: Der Sachverhalt ist nicht klar. Bitte mehr Infos.
Re: ctypes Modul kann nicht mehrere DLLs laden
Verfasst: Mittwoch 9. Mai 2012, 19:54
von marvel82
Folgender Pseudocode sollte weiterhelfen:
Code: Alles auswählen
from ctypes import CDLL
...
cdll = CDLL()
cdll.LoadLibrary("erste.dll")
cdll.machirgendwas()
del cdll
...
cdll = CDLL()
cdll.LoadLibrary("zweite.dll")
cdll.machwiederwas()
del cdll
...
cdll = CDLL()
cdll.LoadLibrary("dritte.dll")
cdll.machwas()
del cdll
...
Re: ctypes Modul kann nicht mehrere DLLs laden
Verfasst: Mittwoch 9. Mai 2012, 21:37
von BlackJack
@marvel82: Pseudocode der falsch ist, also nicht funktionieren kann, hilft nicht so viel weiter. Und eine Fehlerbeschreibung wäre neben lauffähigem Quelltext auch nicht schlecht. Das da führt jedenfalls zu einem `TypeError` weil bei `CDLL()` der Name der Bibliothek fehlt.
Die ``del``-Anweisungen sind überflüssig, die bewirken nicht wirklich etwas, ausser eventuell die Letzte. Aber mit ``del`` versuchen wollen Speicher zu verwalten, sollte man sich gar nicht erst angewöhnen. Das löscht keine Objekte sondern Namen. Das kann eventuell, und irgendwann einmal dazu führen, dass auch Speicher von Objekten freigegeben wird, aber ob und wann das passiert, ist nicht garantiert.
Re: ctypes Modul kann nicht mehrere DLLs laden
Verfasst: Mittwoch 9. Mai 2012, 21:43
von marvel82
Danke für die konstruktive Kritik. Mit dem Pseudocode habe ich improvisiert, da ich erst morgen an den Quellcode rankomme und dachte der Sachverhalt wäre auch so verständlich. Ich werde morgen dann eine neue Beschreibung meines Problems inklusive Quellcode angeben.
Gruss
marvel82
Re: ctypes Modul kann nicht mehrere DLLs laden
Verfasst: Donnerstag 10. Mai 2012, 09:06
von marvel82
Guten Morgen zusammen,
hier der passende Quellcode zu meinem oben beschriebenen Problem
Code: Alles auswählen
#wrapper.py
from ctypes import CDLL, c_wchar_p, c_int, c_bool, c_wchar, POINTER
#==============================================================================
class CmdDLL(object):
"""Wrapper-Klasse für Application-DLL"""
#--------------------------------------------------------------------------
def __init__(self):
#--------------------------------------------------------------------------
"""Konstruktor
"""
self._cmddll = None
#--------------------------------------------------------------------------
def __del__(self):
#--------------------------------------------------------------------------
"""Destruktor
"""
#--------------------------------------------------------------------------
def load_dll(self, appdll=None):
#--------------------------------------------------------------------------
# Application-DLL laden
try:
self._cmddll = CDLL(appdll)
except:
return False
# Typen für Parameterliste und Returnwert festlegen
self._cmddll.initial_update.argtypes = [c_wchar_p, c_wchar_p]
self._cmddll.initial_update.restype = c_bool
self._cmddll.new_document.argtypes = [c_wchar_p]
self._cmddll.new_document.restype = c_bool
self._cmddll.load_document.argtypes = [c_wchar_p]
self._cmddll.load_document.restype = c_bool
self._cmddll.execute_command.argtypes = [c_wchar_p]
self._cmddll.execute_command.restype = c_int
self._cmddll.exists.argtypes = [c_wchar_p]
self._cmddll.exists.restype = c_bool
self._cmddll.get_value.argtypes = [c_wchar_p]
self._cmddll.get_value.restype = c_wchar_p
self._cmddll.set_value.argtypes = [c_wchar_p, c_wchar_p]
self._cmddll.set_value.restype = c_int
self._cmddll.save_document.restype = c_bool
self._cmddll.save_document_as.argtypes = [c_wchar_p]
self._cmddll.save_document_as.restype = c_bool
self._cmddll.close_document.restype = c_bool
self._cmddll.get_last_error.restype = c_wchar_p
self._cmddll.generate_documentation.argtypes = [c_wchar_p]
self._cmddll.generate_documentation.restype = c_bool
# Funktionsnamen für die Funktionen, die einfach an die DLL
# weitergeleitet werden.
self.new_document = self._cmddll.new_document
self.load_document = self._cmddll.load_document
self.execute_command = self._cmddll.execute_command
self.exists = self._cmddll.exists
self.get_value = self._cmddll.get_value
self.set_value = self._cmddll.set_value
self.save_document = self._cmddll.save_document
self.save_document_as = self._cmddll.save_document_as
self.close_document = self._cmddll.close_document
self.get_last_error = self._cmddll.get_last_error
self.generate_documentation = self._cmddll.generate_documentation
return True
Code: Alles auswählen
#------------------------------------------------------------------------------
def startTest(appdll_path, logicdll_file, reference_files_path):
#------------------------------------------------------------------------------
...
# Wrapper erzeugen und Application-DLL laden
cmd = CmdDLL()
ret = cmd.load_dll(appdll_path)
if not ret:
log(u"Fehler: Konnte '%s' nicht laden." %appdll_file)
return
...
Nochmal als Zusammenfassung:
Ich erzeuge während der Laufzeit Instanzen der Klasse CmdDLL, rufe dann die Funktion load_dll() auf und übergebe ihr die gewünschte dll. das klappt auch wunderbar, nur sobald die Funktion startTest() abgearbeitet ist und ich sie zu einem späteren zeitpunkt wieder aufrufe mit anderen argumenten wird bei der erzeugung einer neuer instanz der Klasse CmdDLL die gleiche dll geladen, obwohl ich eine völlig andere übergebe. deshalb bin ich davon ausgegangen das die vorher geladene dll nicht ordnungsgemäss entladen wird, obwohl ich die instanz zerstöre. ich hoffe es ist jetzt klarer
mfg
marvel82
Re: ctypes Modul kann nicht mehrere DLLs laden
Verfasst: Donnerstag 10. Mai 2012, 09:49
von marvel82
Hallo nochmal,
ich habe eine Lösung gefunden !
Das Problem bei dem Modul "ctypes" ist das es die DLL erst entladen kann sobald der gesamte Prozess abgearbeitet, sprich Pyhton beendet wurde. Fakt ist das man mit der aktuellen Implementierung von ctypes keine Möglichkeit hat während der Laufzeit unterschiedliche DLLs zu laden. Abhilfe kann das Modul "multiproccessing" verschaffen, indem man jeden Funktionsaufruf in eigene Prozesse auslagert.
Ich hoffe meinen Erkenntnis bringt euch etwas
MfG
marvel82
Re: ctypes Modul kann nicht mehrere DLLs laden
Verfasst: Donnerstag 10. Mai 2012, 12:20
von Leonidas
marvel82 hat geschrieben:Fakt ist das man mit der aktuellen Implementierung von ctypes keine Möglichkeit hat während der Laufzeit unterschiedliche DLLs zu laden.
Quatsch.
marvel82 hat geschrieben:Abhilfe kann das Modul "multiproccessing" verschaffen, indem man jeden Funktionsaufruf in eigene Prozesse auslagert.
Blödsinn.
marvel82 hat geschrieben:Ich hoffe meinen Erkenntnis bringt euch etwas

Ja, hoffentlich nimmt das keiner Ernst.
Re: ctypes Modul kann nicht mehrere DLLs laden
Verfasst: Donnerstag 10. Mai 2012, 12:57
von marvel82
Hallo Leonidas,
konstruktive Antworten wie "Quatsch, Blödsinn, Ja, hoffentlich nimmt das keiner Ernst" sind natürlich sehr hilfreich. Im moment hat dein Post den Wert von "Total überflüssig", ausser das du in den Raum schmeisst das ich falsch liege. Solltest du jedoch stichhaltige Beweise haben die meine Aussage widerlegen wäre dies anhand eines Beispiels oder Quellcode von Vorteil. So habe ich erstens etwas dazugelernt und zweitens kann jeder User der ein ähnliches Problem hat das Ganze nachvollziehen. Danke im voraus
MfG
marvel82
Re: ctypes Modul kann nicht mehrere DLLs laden
Verfasst: Donnerstag 10. Mai 2012, 13:20
von Leonidas
Hallo marvel82,
marvel82 hat geschrieben:konstruktive Antworten wie "Quatsch, Blödsinn, Ja, hoffentlich nimmt das keiner Ernst" sind natürlich sehr hilfreich. Im moment hat dein Post den Wert von "Total überflüssig", ausser das du in den Raum schmeisst das ich falsch liege.
Das war auch meine Absicht, denn das ist ja auch völlig an den Haaren herbeigezogen was du da behauptest und dann auch noch eventuell anderen empfiehst. Daher wollte ich das schnell widerlegen, bevor andere auf die Idee kommen, das ernst zu nehmen. Wenn du das nicht empfohlen hättest, dann hätte ich nicht so schnell widersprochen.
marvel82 hat geschrieben:Solltest du jedoch stichhaltige Beweise haben die meine Aussage widerlegen wäre dies anhand eines Beispiels oder Quellcode von Vorteil. So habe ich erstens etwas dazugelernt und zweitens kann jeder User der ein ähnliches Problem hat das Ganze nachvollziehen.
Finde es bischen seltsam dass du deine Aussage so einfach in den Raum stellen darfst, aber ich meine Aussage mit funktionierendem Quellcode untermauern soll. Aber hey, hier bitteschön:
Code: Alles auswählen
import ctypes
from ctypes.util import find_library
libc = ctypes.CDLL(find_library("c"))
libm = ctypes.CDLL(find_library("m"))
libc.printf("String formatting, %d\n", 42)
libm.sqrt.restype = ctypes.c_double
libm.sqrt.argtypes = [ctypes.c_double]
print libm.sqrt(23)
Ich importiere hier libc um printf mit String-Formatting zu nutzen und libm um dort die Quadratwurzelfunktion zu nutzen. Ausgabe auf dem Terminal sieht dann so aus:
(Ja, die Quadratwurzel ist auch richtig, habe das mit dem GNOME-Taschenrechner gegengeprüft)
Re: ctypes Modul kann nicht mehrere DLLs laden
Verfasst: Freitag 11. Mai 2012, 09:47
von marvel82
Hmm,
genauso hatte ich mir das auch vorgestellt, jedoch läd er wie bereits erwähnt nur die erste dll. sobald ich die zweite dll übergebe ist es so als würde er dies einfach ignorieren und weiterhin mit der ersten arbeiten. benutzt du ein linux, ich arbeite auf windoof 7. danke für dein beispiel.
Re: ctypes Modul kann nicht mehrere DLLs laden
Verfasst: Freitag 11. Mai 2012, 10:30
von deets
@marvel82
Es kann schlicht nicht sein, was du da behauptest. Denn ctypes ist nur ein duenner Layer ueber dem Loader und der LibFFI. Und *natuerlich* kann man diverse libs laden. Man kann sie allerdings nicht entladen, auch nicht durch del oder sonstewas. Das unterstuetzt schlicht das Betriebssystem nicht. Und damit ist das Problem aller Wahrscheinlichkeit nach in deinem speziellen Usecase zu finden. Kann es sein, dass du immer *dieselbe* DLL (bezogen auf Namen + Funktionen) laden willst - nur in verschiedenen Inkarnationen? Dann ist das so weit logisch, denn das koennen die Loader nicht. Einmal im Prozessraum, immer im Prozessraum.
Abhilfe wuerde uU ein umbenennen vor dem Laden bringen - das muesste man mal ausprobieren. Das ist ein Trick, wie man zB mehrere parallele Python-Interpreter in einen Prozessraum bekommt.
Re: ctypes Modul kann nicht mehrere DLLs laden
Verfasst: Freitag 11. Mai 2012, 11:12
von Leonidas
marvel82 hat geschrieben:sobald ich die zweite dll übergebe ist es so als würde er dies einfach ignorieren und weiterhin mit der ersten arbeiten. benutzt du ein linux, ich arbeite auf windoof 7.
Ja, ich nutze GNU/Linux, aber das tut hier kaum was zur Sache, denn so ein Beispiel würde (gegebenfalls mit anderen DLLs) auf Windows laufen. Jetzt bist du mal an der Reihe uns einen Quellcode zu posten, der nicht funktioniert. Weil so kann man nur rumraten und das verschwendet unser aller Zeit.
Re: ctypes Modul kann nicht mehrere DLLs laden
Verfasst: Freitag 11. Mai 2012, 11:28
von marvel82
Den Quellcode hatte ich bereits weiter oben gepostet, also Erzeugung einer Instanz der Wrapper-Klasse in der ctypes verwendet wird. Denke das ist soweit das wichtigste.
Re: ctypes Modul kann nicht mehrere DLLs laden
Verfasst: Freitag 11. Mai 2012, 11:45
von Leonidas
Da fehlen die nötigen Angaben. Wie etwa was die beiden DLLs sind, die du zu Laden versuchst.
Re: ctypes Modul kann nicht mehrere DLLs laden
Verfasst: Freitag 11. Mai 2012, 11:47
von EyDu
marvel82 hat geschrieben:Den Quellcode hatte ich bereits weiter oben gepostet, also Erzeugung einer Instanz der Wrapper-Klasse in der ctypes verwendet wird. Denke das ist soweit das wichtigste.
Der Code ist weder lauffähig noch annähernd minimal. Wie soll man da das von dir beschriebene Verhalten tesen können?
Re: ctypes Modul kann nicht mehrere DLLs laden
Verfasst: Freitag 11. Mai 2012, 11:48
von marvel82
Die Dlls die ich übergebe sind von mir selber implementiert worden, also funktionen in c++ mit c schnittstelle für python.
Re: ctypes Modul kann nicht mehrere DLLs laden
Verfasst: Freitag 11. Mai 2012, 12:27
von Hyperion
marvel82 hat geschrieben:Die Dlls die ich übergebe sind von mir selber implementiert worden, also funktionen in c++ mit c schnittstelle für python.
Dann sollte es ja noch weniger ein Problem sein, diese zu veröffentlichen. Kannst ja auch den Quellcode veröffentlichen und dazu ggf. Infos zum Kompilieren. Es soll hier ja einige geben, die sich so etwas dann schon selber backen können

Re: ctypes Modul kann nicht mehrere DLLs laden
Verfasst: Freitag 11. Mai 2012, 22:37
von jerch
Auch unter C/C++ kannst Du mit dlclose resp. FreeLibrary das "Entladen" einer shared lib aus dem Speicher nicht erzwingen.
Ich kann Dein Problem in keinster Weise nachvollziehen, von Assembler-Libs über Pascal- bis C/C++-Libs lädt ctypes alles und das auch mehrfach, solange es den Containerformaten und unterstützten Aufrufkonventionen entspricht. Hast Du mal versucht, Deine Libs in C einzubinden? Vllt. fehlt irgendwo eine Directive beim Erstellen der Libs?
Ein auf das Wesentliche eingekürztes Bsp. wäre hilfreich.