DLL-Funktionen werden nicht gefunden =>[ILINK32 Fehler]
-
Hallo,
ich möchte auf einige Funktionen aus der DLL "uxtheme.dll" zugreifen. Diese DLL liegt unter ..\WINDOWS\system32. Die DLL ist bekanntlich für das XP-Aussehen mit zuständig.
Der Zugriff soll nicht statisch erfolgen sondern dynamisch (Laufzeit).Mein Lade-Ansatz erfolgt in etwa nach folgendem Schema:
//h. typedef bool __stdcall pIsThemeActive(void); //WINAPI: BOOL IsThemeActive(VOID); typedef //weitere Funktionen usw. HMODULE hmyThemeAPI; void LoadXPThemeAPI(void); //cpp void LoadXPThemeAPI(void){ hmyThemeAPI = LoadLibrary("uxtheme.dll"); if (hmyThemeAPI != 0) { pIsThemeActive* IsThemeActive = (pIsThemeActive*) GetProcAddress(hmyThemeAPI, "IsThemeActive"); //weitere Funktionen usw. }
Mit einer kleinen Demo möchte ich prüfen, ob die DLL geladen wurde: Leider meldet der Linker die folgenden Fehler:
[ILINK32 Fehler] Error: Nicht auflösbares externes '__stdcall IsThemeActive()' referenziert von C:\...\CBUILDER2009\TEST\DLL\DEBUG\DEMO.OBJ
usw.1) Was mache ich da falsch? Kann mir jemand sagen, warum der Linker die gewünschten Funktionen nicht findet?
2) Muß ich "uxtheme.dll" in das Projekt einbinden? (Eine LIB-Datei bzw. Uxtheme.h werden hier ja nach meinem Verständnis nicht gebraucht oder?)
3) Muß ich unter Projektoptionen eine bestimmte Einstellung wählen?
-
Du lädst nur die DLL. Die DLL-Funktionen müssen aber noch gesondert importiert werden. Das macht man am besten mit dem DOS-Utility implib(mydll.lib,mydll.dll) und der Einbindung der so erzeugten Importbibliothek mydll.lib in das Projekt.
-
Das ist bei seiner Lademethode nicht nötig.
Der Linkerfehler hat eher nichts mit der dll zu tun. Ich denke, dass hier irgendwo eine Funktionsdeklaration (__stdcall IsThemeActive()) vorhanden ist die jetzt aber nicht mehr nötig ist.
-
Danke für Eure Kommentare.
Bin mittlerweile der gleichen Meinung wie @Braunstein. Die DLL uxtheme.dll muß alleine ausreichen. Sie braucht auch nicht ins Projekt geladen werden.Ich habe mittlerweile folgende Feststellung gemacht:
Wenn ich die DLL-Funktion IsThemeActive() nicht aufrufe läuft die Demo ohne Fehler. Es funktioniert auch der Ladevorgang.pIsThemeActive* IsThemeActive = pIsThemeActive*)GetProcAddress(hmyThemeAPI, "IsThemeActive");
Wenn man mit dem Debugger den Vorgang verfolgt, wird LoadXPThemeAPI(void) ordnungsgemäß durchlaufen und der Zeiger IsThemeActive erhält auch seine Adresse (was natürlich nicht ausschließt, dass hier etwas faul ist
)
Erst wenn ich Funktion IsThemeActive() im Demoprogramm aufrufen möchte
void __fastcall TForm1::Button1Click(TObject *Sender) {if (IsThemeActive()) ShowMessage("hat geklappt!");}
erhalte ich den Linker-Fehler.
Es deutet daraufhin, dass irgendetwas beim Aufruf der Funktion nicht stimmt.
@Braunstein, vielleicht könntest Du noch ein Stück weiter helfen?!
-
Ist der Funktionszeiger 'IsThemeActive' denn bei dir als Member der Klasse deklariert (in deinem ersten Beitrag jedenfalls nicht)?
Da du jedoch einen Linker-Fehler erhältst (und keinen Compiler-Fehler) mußt du irgendwo noch eine Deklaration der Funktion vorliegen haben (evtl. kommt diese Deklaration auch direkt aus der <windows.h>) - daher benenne deine Variable mal um (ich benenne den Funktionszeiger daher immer als F... und die Variable dann als p...).
-
Hallo und willkommen @Th69, vielleicht hast Du noch eine Idee.
Ich habe mein 1.Beispiel zur Klärung des Problems übungshalber nochmals etwas umgestellt und ein paar Anregungen aus dem Internet eingebaut.
Dann habe ich mit dem Builder eine DLL erstellt, in der die Funktion "AddiereWerte" liegt. Diese sehr einfache Funktion addiert nur 2 Integers.
Im Demoprogramm funktioniert der Zugriff auf meine selbstgebastelte Project2.dll einwandfrei.
Mit dem gleichen Schema erhalte ich aber keinen Zugriff auf IsThemeActive()aus uxtheme.dll.
Langsam gehen mir die Ideen aus. Das Programm ist so stark abgespeckt, da gibt es keine anderen Fehlermöglichkeiten. Es gibt keine zusätzlichen Deklarierungen etc., nur die Standard-Header für eine TForm.
Müssen Windows-DLL's vielleicht mit einem anderem Namen aufgerufen werden?
Hat jemand vielleicht ein Bsp. wie er eine Windows-DLL erfolgreich anschließt? Im Internet habe ich immer nur Zugriffe auf selbst erstellte DLLs gesehen.
Antworten werden gerne gelesen.//=========== DLLImport.h typedef int pAddiereWerte (int, int); typedef bool pIsThemeActive(void); //----------------------------------------------- int AddiereWerte(int z1, int z2); bool IsThemeActive(void); //=========== DLLImport.cpp int AddiereWerte(int z1, int z2){ int Result; pAddiereWerte* AddiereWerte = NULL; //Variable für Funktionszeiger HMODULE h = LoadLibrary(L"Project2.dll"); //selbstgebastelte DLL laden. if (h != 0) AddiereWerte = (pAddiereWerte*)GetProcAddress(h, "_AddiereWerte"); //Unterstrich nötig, da kein "__stdcall" if (AddVals != NULL) Result = AddVals(z1, z2); FreeLibrary(h); return Result; } //------- bool IsThemeActive(void){ bool Result; pIsThemeActive* IsThemeActive = NULL; HMODULE h = LoadLibrary(L"uxtheme.dll"); //Windows DLL laden, das macht er if (h != 0) //h ist verschieden von NULL IsThemeActive = (pIsThemeActive*)GetProcAddress(h, "_IsThemeActive"); //Funktionszeiger setzen if (IsThemeActive != NULL) //macht er nicht, das ist immer NULL, leider! Result = IsThemeActive(); else Result = false; FreeLibrary(h); //DLL freigeben return Result; } //=========== Demo.cpp =>Eine Form mit 2 TButtons, mehr nicht! void __fastcall TForm1::Button1Click(TObject *Sender) { if (IsThemeActive()) ShowMessage("hat geklappt!"); } //---------- void __fastcall TForm1::Button2Click(TObject *Sender){ int Ergebnis = AddiereWerte((5, 99); //DLL-Funktion wird aufgerufen ShowMessage(IntToStr(Ergebnis)); } //Ergebnis: Beim Klick auf Button1 passiert nix. Beim Klick auf Button2 => wie gewünscht "104"
-
Hallo thunderbol4,
laut "Dependency Walker" (www.dependencywalker.com) mußt du nur "IsThemeActive" angeben, d.h. ohne Unterstrich (bei den C-DLLs ist es meistens aber Standard mit Unterstrich).
P.S: Bei 'AddiereWerte' benutzt du zwei verschiedene Variablen: 'AddiereWerte' und 'AddVals' - dürfte also gar nicht funktionieren -)
Außerdem habe ich dir ja schon geschrieben, daß es schlecht ist, die Variable für den Funktionszeiger genauso zu benennen wie die Funktion...
-
Hallo @Th69, danke für Deine Antwort
hast ja völlig Recht@Th69 schrieb:
'AddiereWerte' und 'AddVals' - dürfte also gar nicht funktionieren -)
Das kommt von der ständigen Hin- u Herkopiererei, werde versuchen mich zu bessern.
Keine Ahnung, warum sich die Funktion(en) "IsThemeActive()",".." aus uxtheme.dll nicht aufrufen lassen. Jedenfalls habe ich bei der Namensgebung mit 1 Unterstrich, mit 2 Unterstrich, ohne Unterstrich und..und..und so ziemlich alles durchprobiert, ohne Erfolg. Mit meinem schon etwas angestaubten Idapro habe ich die benannten Funktionen in der DLL inspiziert. Die Funktionsnamen habe ich dort mit "_IsThemeActive@0", "_OpenThemeData@8","_DrawThemeBackground@24" usw. gesehen.
Aber auch damit funktioniert's nicht.
Wie auch immer. Ich gebe das jetzt erst einmal auf:
Normalerweise ist es ja auch nicht nötig auf uxtheme.dll direkt zuzugreifen. Über das Anklicken der RTL in den Projektoptionen oder durch Aufnahme d. Kompo XPManifest ist für ein richtiges XP-Style Verhalten des Programms ja gesorgt.Allerdings hätte mich schon interessiert, ob ein Zugriff auf eine Windows eigene DLL möglich ist! Also im Internet habe ich das nirgends gesehen, dort ging es immer nur um "Hausmacherware"