none
Einbinden von DLLs RRS feed

  • Frage

  • Hi!

    Wie kann ich eine Klassenbibliothek so in ein Projekt einbinden, dass ich den Pfad der DLL erst zur Laufzeit angeben muss. Ich möchte nämlich, dass der Nutzer über einen Dialog auswählen kann, welche DLL er benutzen möchte. Über "Verweise" geht das warscheinlich nicht, da ich nicht unbedingt weiß, in welchem Ordner die DLL liegt.

    Danke schon mal im Voraus!

    Donnerstag, 10. März 2011 17:58

Antworten

  • Langsam zweifle ich daran, dass Du liest was man Dir schreibt.
    Nochmal Schrit für Schritt:

    1. Bau ein "Interface" aus puren virtuellen Funktionen.
    2. Leite Deine Klasse in der DLL von diesem Interface ab.
    3. Baue ene Funktion die nun ein Objekt dieser Klasse anlegt und den Interface Zeiger an die aufrufende Funktion zurückgibt.

    Du benötigst mindestens ein Interface. Sicher kannst Du auch einen void* Zeiger auf eine Klasse zurückgeben, aber was würde das nutzen? Es muss ein Zeiger eines bestimmten bekannten Typs sein.

    BTW: COM macht das auch so. Du köntest also auch COM verwenden ;)
    Ich habe das IMHO jetzt schon dreimal geschrieben.

     


    Martin Richter -- MVP for VC++ [Germany] -- http://blog.m-ri.de
    Dienstag, 15. März 2011 07:08
    Moderator
  • Ich habe geantwortet. Du hast eine Lösung erhalten. Die Begriffe sind bekannt.

    Ich verbringe mene Zeit i.A. nicht damit alles haarklein duchzukauen. Dazu habe ich keine Zeit, dnen ich arbeite nebenbei auch noch.
    Ich erwarte etwas Eigeninitiative. ;)

    Wenn es schwierig wäre dazu Informationen zu finden, würde ich Deinen Ton und Dein Nachfragen ja noch verstehen. Aber es ist so trivial entsprechenden Beispielcode zu finden, dass ich nicht verstehen kann, dass Du fast eine Woche auf eine Antwort hier im Forum wartest und scheinbar noch beleidigt bist.

    Folge diesem Link.


    Martin Richter -- MVP for VC++ [Germany] -- http://blog.m-ri.de
    Montag, 21. März 2011 07:53
    Moderator

Alle Antworten

  • Entweder über /DELAYLOAD und LoadLibrary
    http://msdn.microsoft.com/de-de/library/yx9zd12s

    oder via LoadLibrary/GetProcAddress


    Jochen Kalmbach (MVP VC++)
    Donnerstag, 10. März 2011 20:11
  • Willst Du das in C++/CLI machen oder nativ?

    Ich würde Dir raten ein reines Interface zu erstellen.
    Alle DLLs verfügen nur über eine Funktion (GetInterface), die diesen Interface Zeiger dann bei Bedarf liefern.

    Du kannst also dieDLL laden, GetInterface aufrufen und ein völlig autarkes System.


    Martin Richter -- MVP for VC++ [Germany] -- http://blog.m-ri.de
    Freitag, 11. März 2011 07:48
    Moderator
  • Hi und danke schon mal für die Antworten!

    Entweder über /DELAYLOAD und LoadLibrary
    http://msdn.microsoft.com/de-de/library/yx9zd12s


    Ich denke, dass es sich bei /DELAYLOAD und LoadLibrary um Linker-Optionen handelt und deshalb sind diese für ein dynamisches Einbinden nicht geeignet, oder?

    oder via LoadLibrary/GetProcAddress
    Willst Du das in C++/CLI machen oder nativ?

    Ich will das in C++/CLI machen (genau wie die DLL) und da gibt es doch LoadLibrary bzw. GetProcAddress nicht, oder täusche ich mich?

    Ich würde Dir raten ein reines Interface zu erstellen.
    Alle DLLs verfügen nur über eine Funktion (GetInterface), die diesen Interface Zeiger dann bei Bedarf liefern.

    Du kannst also dieDLL laden, GetInterface aufrufen und ein völlig autarkes System.

    Mir geht es nicht darum die Funktionen aus der DLL aufzurufen, sondern darum, wie ich die DLL an sich überhaupt ersteinmal laden kann.

    • Bearbeitet developer1800 Freitag, 11. März 2011 17:59 Sorry, dass mir der Eintrag etwas hochgerutscht ist!
    Freitag, 11. März 2011 17:58
  • > Mir geht es nicht darum die Funktionen aus der DLL aufzurufen, sondern darum, wie ich die DLL an sich überhaupt ersteinmal laden kann.

    Du hast LoadLibrary doch gefunden... damit lädt man eine DLL:


    Martin Richter -- MVP for VC++ [Germany] -- http://blog.m-ri.de
    Freitag, 11. März 2011 18:48
    Moderator
  • C++/CLI ist eine reine InterOp Sprache. Und somit kann man da sowohl .NET machen, als auch native Code verwenden.

    Und laden tut man eine DLL dynamisch mit "LoadLibrary".


    Jochen Kalmbach (MVP VC++)
    Freitag, 11. März 2011 18:54
  • Hi!

    Ich habe jetzt wo gelesen, dass man mit LoadLibrary allerdings keine Klassen laden kann und bei mir funktioniert das auch nicht. Aber ich muss die Klassen aus den DLLs laden können. Gibt es denn keine andere Möglichkeit?

    Danke schon mal!

    Samstag, 12. März 2011 12:06
  • Wie gesagt. Schau Dir mal /DELAYLOAD an. Das ist die einzige Möglichkeit, wenn Du auch noch Klassen verwendest.


    Jochen Kalmbach (MVP VC++)
    Samstag, 12. März 2011 13:28
  • Hi

    Wenn ich eine DLL über "Verweise" oder auch über /DELAYLOAD einbinde, muss ich ja den Pfad zu der DLL auf meinem aktuellen Computer angeben, jetzt habe ich aber das Problem, dass die DLLs auf einem anderen Computer nicht im Programmverzeichnis liegen sollen. Wie kann ich es also machen, dass die DLL auf meinem Computer in C:\Test.dll liegt auf einem Zielcomputer aber aus C:\Users\User\Test.dll aufgerufen wird?

    Gruß, developer1800

    Samstag, 12. März 2011 13:49
  • Hast Du es denn mal probiert?

    Gebe /DELAYLOAD für diese DLL an und lade dann die DLL via LoadLibrary mit dem kompletten Pfad auf dem Zielsystem.


    Jochen Kalmbach (MVP VC++)
    Samstag, 12. März 2011 14:46
  • Die Lösung hast Du schon bekommen.
    Das ist der Weg über Interfaces. Es ist genau die selbe Methode die auch COM benutzt. Du hast einen definierten Einsprüng in der DLL und besorgst Dir ein neutrales Interface (Klasse).


    Martin Richter -- MVP for VC++ [Germany] -- http://blog.m-ri.de
    Samstag, 12. März 2011 15:33
    Moderator
  • Ich probiere es jetzt mit LoadLibrary, aber da kommen nur Fehlermeldungen, wie

    "LoadLibrary": Bezeichner wurde nicht gefunden.

    Kann vielleicht mal jemand ein Codebeispiel posten?

    Samstag, 12. März 2011 16:38
  • > Kann vielleicht mal jemand ein Codebeispiel posten?

    Was ist das für ein Projekt.
    Nativ C++?
    Hast Du den windows.h Header included?


    Martin Richter -- MVP for VC++ [Germany] -- http://blog.m-ri.de
    Samstag, 12. März 2011 17:01
    Moderator
  • Danke, ich hatte den windows.h Header vergessen. Jetzt habe ich etwas ausprobiert, es wird auch richtig compiliert, aber zur Laufzeit tritt dann folgender Fehler auf:
    Es wurde versucht, im geschützten Speicher zu lesen oder zu schreiben. Dies ist häufig ein Hinweis darauf, dass anderer Speicher beschädigt ist.

    Hier ist mein Code:

    FARPROC pFunc;
    HMODULE hMod = LoadLibrary((LPCWSTR) "ThisTest.dll");
    pFunc = GetProcAddress(hMod, "GetClass"); //????
    pFunc();
    
    Was ist daran falsch? An mehreren Stellen im Internet habe ich das genau so gefunden.

    Sonntag, 13. März 2011 15:55

  • FARPROC pFunc; HMODULE hMod = LoadLibrary((LPCWSTR) "ThisTest.dll"); pFunc = GetProcAddress(hMod, "GetClass"); //???? pFunc();

    Was ist daran falsch? An mehreren Stellen im Internet habe ich das genau so gefunden.

    Der cast für den DLL Namen ist falsch! ern Du ein Unicode Projekt hast muss es
    HMODULE hMod = LoadLibrary(L"ThisTest.dll");

    lauten. Oder Du verwendest gleich die T Notation

    HMODULE hMod = LoadLibrary(_T("ThisTest.dll"));

    Die geht bei ANSI und UNICODE.

    Ansonsten ist der Code OK wie ich das sehe.


    Martin Richter -- MVP for VC++ [Germany] -- http://blog.m-ri.de
    Sonntag, 13. März 2011 17:23
    Moderator
  • Danke für Deine Antwort!

    Ich habe beide Möglichkeiten ausprobiert, aber bei der T Notation kommt folgende Fehlermeldung:

    "_T": Bezeichner wurde nicht gefunden.

    Und Dein anderer Vorschlag funktioniert zwar beim compilieren, während der Laufzeit kommt aber wieder der gleiche Fehler, dabei ist auf der linken Seite ein grüner Pfeil vor der Zeile zu sehen, in der nur pFunc(); steht!

    Sonntag, 13. März 2011 17:58
  • Ich würde Dir arten erst mal ein wenig Basics um das Programmieren in C/C++ zu lernen.

    _T gibt aus wenn Du tchar.h includest, oder andere CRT Header.

    Du hast keine Fehlerprüfung und GetProcAdress liefert mit Sicherheit kein Ergebnis. Also NULL, wenn Du diesen Zeiger verwendets muss es krachen.

    Deine DLL hat offensichtlich keine Funktion mit dem Namen.
    Schau Dir die DLL mit Depends an.
    Evtl. hast Du nicht extern C verwendet damit das Name-Mangeling das C++ macht nicht berücksichtigt.
    Oder die Funktion wurde automaisch ohne DEF Datei exportiert und hat vermutlich einen Unterstrich am Namensanfang.
    Wie schon gesagt, schau dir es mit Depends an.


    Martin Richter -- MVP for VC++ [Germany] -- http://blog.m-ri.de
    Sonntag, 13. März 2011 18:46
    Moderator
  • Danke für deine Hilfe, ich hab mir die DLL nochmal mit Depends angeschaut und dann festgestellt, das ich versehentlich das declspec vergessen hatte. Jetzt funktioniert es.

    Aber ist es möglich über eine Funktion aus einer DLL einen Zeiger auf ein Klassenobjekt einer in der DLL enthaltenen Klasse zurückzugeben, auch wenn die Klasse der Anwendung, die die DLL verwendet nicht bekannt ist?

    Montag, 14. März 2011 18:59
  • Langsam zweifle ich daran, dass Du liest was man Dir schreibt.
    Nochmal Schrit für Schritt:

    1. Bau ein "Interface" aus puren virtuellen Funktionen.
    2. Leite Deine Klasse in der DLL von diesem Interface ab.
    3. Baue ene Funktion die nun ein Objekt dieser Klasse anlegt und den Interface Zeiger an die aufrufende Funktion zurückgibt.

    Du benötigst mindestens ein Interface. Sicher kannst Du auch einen void* Zeiger auf eine Klasse zurückgeben, aber was würde das nutzen? Es muss ein Zeiger eines bestimmten bekannten Typs sein.

    BTW: COM macht das auch so. Du köntest also auch COM verwenden ;)
    Ich habe das IMHO jetzt schon dreimal geschrieben.

     


    Martin Richter -- MVP for VC++ [Germany] -- http://blog.m-ri.de
    Dienstag, 15. März 2011 07:08
    Moderator
  • Ich hatte das durchaus gelesen, dachte nur Du könntest eine etwas genauere Beschreibung abgeben. Ich hab nämlich noch nie mit Interfaces gearbeitet und werde auch aus anderen Internetseiten nicht schlau. Könntest Du das also entweder an einem kleinen Beispiel nochmal erklären oder auf eine Internetseite verweisen, wo genau so etwas, wie Du beschreibst gemacht wird?

    Das wäre wirklich sehr nett von Dir!

    Dienstag, 15. März 2011 18:20
  • Antwortet hier noch jemand ?
    Sonntag, 20. März 2011 18:33
  • Ich habe geantwortet. Du hast eine Lösung erhalten. Die Begriffe sind bekannt.

    Ich verbringe mene Zeit i.A. nicht damit alles haarklein duchzukauen. Dazu habe ich keine Zeit, dnen ich arbeite nebenbei auch noch.
    Ich erwarte etwas Eigeninitiative. ;)

    Wenn es schwierig wäre dazu Informationen zu finden, würde ich Deinen Ton und Dein Nachfragen ja noch verstehen. Aber es ist so trivial entsprechenden Beispielcode zu finden, dass ich nicht verstehen kann, dass Du fast eine Woche auf eine Antwort hier im Forum wartest und scheinbar noch beleidigt bist.

    Folge diesem Link.


    Martin Richter -- MVP for VC++ [Germany] -- http://blog.m-ri.de
    Montag, 21. März 2011 07:53
    Moderator