Hallo, ich sehe immer wieder Threads, wo es Probleme beim Registrieren einer DLL gibt. Z.B. hier: http://stackoverflow.com/questions/22933957/unable-to-register-my-dll-using-regsvr32-but-via-ide-works Was hat das mit dem regsvr32 auf sich? Wozu überhaupt registrieren? Die DLL wird auf den Rechner kopiert und die Applikation ruft darin Funktionen auf - das geht doch auch so. Gruß Peter
Peter schrieb: > das geht doch auch so. Nicht wenn das eine COM-DLL ist. Dann wird die über eine GUID statt Pfad/Dateiname angesprochen.
Da bist du auf COM gestoßen. Im Kern ist COM die Spezifikation einer binären Schnittstelle. Meist wird C++ zur Implementierung benutzt, weil das am leichtesten geht. Kein Zufall, sondern genauso geplant. Richtig, eine herkömmliche DLL braucht nicht registriert werden. Sie wird entweder über ihre Importbibliothek (kleine LIB Datei) mit der EXE verlinkt oder zur Laufzeit via LoadLibrary geladen. Und fertig ist die Laube. Aber was, wenn man systemweit Komponenten bereitstellen möchte, ohne dem Client das Implementierungsdetail »DATEINAME.DLL« bekannzumachen? Weil vielleicht verschiedene Versionen der Komponente parallel existieren müssen? Dann braucht man eine Indirektion, und die geht über die Windows Registrierungsdatenbank. Die zu registrierende DLL muß DllRegisterServer implementieren und darüber ihre API Kennungen (GUIDs für Klassen und Schnittstellen: CLSID und IID) dem System bekanntmachen. DllRegisterServer http://msdn.microsoft.com/en-us/library/windows/desktop/ms682162(v=vs.85).aspx COM Registry Keys http://msdn.microsoft.com/en-us/library/windows/desktop/ms678477%28v=vs.85%29.aspx Ein Client muß dann nur die entsprechenden GUIDs kennen und kann über CoCreateInstance und QueryInterface versuchen, Zeiger auf die Schnittstellen der Komponente zu laden. Es steckt einiges mehr hinter COM und für einen Programmierer denk ich ist es ein sehr interessantes Modell, das aber ein wenig Lernaufwand erfordert. Ein Riesenbatzen von Windows beruht auf COM, es ist also kein Schnickschnack, sondern eine tragende Säule des Systems.
Es gibt bei COM-Dlls auch die Möglichkeit sie ohne Registrierung zu verwenden. Das kann man einsetzen, wenn man Software ohne Installation und Admin Rechte verwenden will. Dafür muss dann aber wieder der Name der DLL bekannt sein.
Erstmal vielen Dank für die ganzen Auskünfte. Die haben mir sehr geholfen! Micha Lu schrieb: > Aber was, wenn man systemweit Komponenten bereitstellen möchte, ohne dem > Client das Implementierungsdetail »DATEINAME.DLL« bekannzumachen? Weil > vielleicht verschiedene Versionen der Komponente parallel existieren > müssen? Das verstehe ich nicht ganz: 1. Was sind systemweite Komponenten? 2. Worin genau liegt das Problem jedem Client (was meinst Du mit Client in dem Fall?) ein LoadLibrary("MyDLL.dll") zu verpassen? 3. verschiedene Versionen der Komponente? Wieso verschiedene Komponenten? Beispiel? Peter II schrieb: > Es gibt bei COM-Dlls auch die Möglichkeit sie ohne Registrierung zu > verwenden. Sind COM-DLLs und normale DLLs zwei verschiedene paar Schuhe oder unterscheiden die sich nur in der Implementierung von DllRegisterServer() / DllUnregisterServer() ? Mit anderen Worten: Wenn ich die beiden Funktionen in der normalen DLL einfüge, wird sie dann zur COM-DLL? Gruß Peter
Peter schrieb: > Sind COM-DLLs und normale DLLs zwei verschiedene paar Schuhe O ja. COM sieht eine völlig andere Art des Aufrufs von in DLLs (bzw. anderen COM-Servern) enthaltenen Funktionen vor, als das bei normalen DLLs üblich ist. Das Stichwort hier lautet "Automation", und ermöglicht es, Funktionen aus COM-DLLs u.a. auch aus VB-Script heraus zu verwenden. Der unschöne Aspekt daran ist, daß gerade das Interface mit C/C++ und das Debuggen des ganzen Krams ein ziemlicher Krampf im Arsch ist. > Wenn ich die beiden Funktionen in der normalen DLL > einfüge, wird sie dann zur COM-DLL? Nein.
Peter schrieb: > Micha Lu schrieb: >> Aber was, wenn man systemweit Komponenten bereitstellen möchte, ohne dem >> Client das Implementierungsdetail »DATEINAME.DLL« bekannzumachen? Weil >> vielleicht verschiedene Versionen der Komponente parallel existieren >> müssen? > > Das verstehe ich nicht ganz: > 1. Was sind systemweite Komponenten? Systemweit verfügbar, so wie eine DLL in System32 oder WinSxS. Gedacht im Gegensatz zu einer DLL im Unterordner irgendeiner Anwendung im Programmverzeichnis, welcher nicht im Suchpfad liegt sondern nur ebenjener Anwendung bekannt ist und sonst nicht genutzt wird. Die Komponente ist eben das COM Ding: Ein Satz zusammengehöriger Schnittstellen, die IUnknown ordnungsgemäß implementieren. Eine Komponente ist, was die COM Spezifikation beschreibt. Implementiert wird sie in einer oder mehreren DLLs, aber die DLL ist dabei wirklich nur ein Implementierungsdetail und hat an sich nichts mit COM zu tun. Aber irgendwie muß man sie ja implementieren, und in Windows bot sich da eben die DLL an, die sich ja schon in der Produktion bewährt hatte. :) > 2. Worin genau liegt das Problem jedem Client (was meinst Du mit Client > in dem Fall?) ein LoadLibrary("MyDLL.dll") zu verpassen? Ein Client ist der Nutzer einer Funktionalität. Wenn ich eine DLL habe, dann sind die davon abhängigen Exen die Clients. Wenn ich eine Funktion habe, dann nenne ich die aufrufenden Stellen Clientcode. Worin das Problem liegt? Für C gibt es kein Problem. Für C ist die DLL vollkommen ausreichend. Für C ist alles in Butter. Aber nun gibt es ja auch C++. Objekte und so. Wollen ja die meisten haben. Und da gehen die Probleme los. Stichwort »name mangling«: Um dem Linker die Überladungen einer Funktion unterscheidbar zu machen, kodiert der Compiler die Argumente der Funktion in den Symbolnamen. Und da kocht jeder Compiler sein eigenes proprietäres Süppchen. Es gibt keinen Standard für diese Umbenennung, und damit keine Interoperabilität. Ich brauch genau den Linker, mit dem die Kompilate erstellt wurden, gegen die ich linken will. Den Quellcode hab ich vielleicht nicht, weil ich er der Firma Xy gehört und nicht offenliegt. Stichwort »binary interface«: Wenn ich einer Klasse in C++ einen privaten Member dazugebe, ändert sich die binäre Definition der Klasse. Sagen wir, hier kommt Version 2 der Klasse CBlubbel, die ist viel besser als Version 1, aber dafür mußte ein privater Member eingeführt werden. Privat, also kann ich immer noch dagegen kompilieren, ohne Änderungen am Clientcode. Ja, aber wenn ich nun im System meine Blub.dll durch die neue Version ersetze, werden alte Clients sehr wahrscheinlich die Grätsche machen, weil sie den Speicherplatz für CBlubbel Exemplare falsch berechnen, nämlich ohne den Platz für den neuen privaten Member. Also kann ich meine Blub.dll nicht so einfach ersetzen; ich müßte sie Blub2.dll nennen. Und bei der nächsten Verbesserung wieder. Und so weiter, fröhliche Vermüllung, wer soll das wieder aufräumen? Wenn ich die Schnittstelle meiner C++ Bibliothek als »extern "C"« auslege, dann habe ich diese Probleme nicht; aber dann kann ich eben (wie mit C) nur globale Funktionen anbieten, und keine Objekte, weil »extern "C"« die Implementierungsgrundlagen von C++ OO außer Kraft setzt. > 3. verschiedene Versionen der Komponente? Wieso verschiedene > Komponenten? Beispiel? Version 1 von Bla.dll hat einen schweren Fehler oder läuft inakzeptabel langsam. Nun kommt Version 2 mit dem Fix. Dieser verändert leider die binäre Schnittstelle von CBlabla. Kein Problem für laber.exe, welche ich zusammen mit Bla.dll in einer neuen Version ausliefere. Aber Pech für schnack.exe, welche von einem anderen Anbieter gegen Bla.dll entwickelt wurde und nicht zeitnah aktualisiert werden kann. Stell dir einfach vor, du bist Microsoft oder Adobe oder auch eine kleine Firma oder ein Einmannbetrieb, aber jedenfalls ein Anbieter fundamentaler C++ OO Funktionalität mit Clientcode außerhalb deiner Kontrolle. Da mußt du immer kompatibel bleiben. Und trotzdem verbessern und bereinigen und liefern. Mit C++ Bordmitteln geht das nicht. COM wurde erdacht (von 1988-93 bei Microsoft), um dies Problem zu lösen, und es funktioniert.
Micha Lu schrieb: > Stichwort »name mangling«: Um dem Linker die Überladungen einer Funktion > unterscheidbar zu machen, kodiert der Compiler die Argumente der > Funktion in den Symbolnamen. Und da kocht jeder Compiler sein eigenes > proprietäres Süppchen. Es gibt keinen Standard für diese Umbenennung, > und damit keine Interoperabilität. Ich brauch genau den Linker, mit dem > die Kompilate erstellt wurden, gegen die ich linken will. Den Quellcode > hab ich vielleicht nicht, weil ich er der Firma Xy gehört und nicht > offenliegt. Das kann ich unterdrücken: extern "C" ... , aber das schreibst Du ja auch wie ich sehe ... Micha Lu schrieb: > Wenn ich die Schnittstelle meiner C++ Bibliothek als »extern "C"« > auslege, dann habe ich diese Probleme nicht; aber dann kann ich eben > (wie mit C) nur globale Funktionen anbieten, und keine Objekte, weil > »extern "C"« die Implementierungsgrundlagen von C++ OO außer Kraft > setzt. Globale Funktionen? Ist doch egal, wenn ich denen einen Index/Zeiger auf eine DLL-interne Struktur mitgebe und die verschiedenen Objekte ebenfalls in der DLL in einer Liste sammle und verwalte, oder nicht?
Peter schrieb: > st doch egal, wenn ich denen einen Index/Zeiger auf > eine DLL-interne Struktur mitgebe und die verschiedenen Objekte > ebenfalls in der DLL in einer Liste sammle und verwalte, oder nicht? Das Konzept ist jedenfalls nicht neu; was wohl verbirgt sich hinter einem "Handle"? Eben. Genau für diese Situation ist das da.
Ja, handle, natürlich kann man das machen, und erwiesenermaßen funktioniert das hervorragend; dann hat man aber »nur« eine API à la Win32 und keine »echte OO API«. COM dagegen erlaubt mehr OO in der API. Wie wichtig das nun ist … vielleicht Geschmacksfrage. Aber der Nutzen von COM beschränkt sich ja nicht auf API Kosmetik.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.