Probleme bei dynamischem Laden von DLLs
-
Hallo zusammen,
gerade eben habe ich mich an das Laden von DLLs gewagt und bin gescheitert. Ich bitte um Hilfe.
Das Problem: Ich habe mir eine Klasse geschrieben, die dynamisch DLLs laden können sollte. So sieht sie aus:
bool DLLLader::dllLaden(char* dllname) { if (!DllInstance) DllInstance = LoadLibrary(dllname); // DLL laden if (DllInstance != NULL) { status = "DLL wurde geladen."; return true; } else { status = "DLL wurde nicht geladen."; return false; } } bool DLLLader::dllEntladen(char* dllname) { if (DllInstance) { if (FreeLibrary(DllInstance)) { DllInstance = NULL; // DLL entladen } } if (!DllInstance) { status = "DLL wurde entladen."; return true; } else { status = "DLL wurde nicht entladen."; return false; } } TObject* DLLLader::dllFunktionLaden(char* funktionsname) { // Funktionstyp deklarieren typedef TObject* (__stdcall *IMPFUNC) (String); IMPFUNC DllFunktion; // Deklaration für die DLL-Funktion if (DllInstance) { DllFunktion = (IMPFUNC)GetProcAddress(DllInstance, funktionsname); if (DllFunktion) { return DllFunktion(funktionsname); } else status = "Funktionsname existiert nicht!"; } else { status = "Bitte DLL laden!"; } return NULL; }Problem eins:
Mit dem Aufrufdlllader = new DLLLader(); bool erfolg = dlllader->dllLaden("Datenbankverbindung.dll");bekomme ich immer true zurück. Egal wie der Dateiname lautet, es ist immer ein Erfolg. Wenns denn wahr wäre, wäre ich froh...
Problem zwei (was vielleicht damit zusammenhängt):
lade ich eine Funktion, z.B.(TADOConnection*)dlllader->dllFunktionLaden("verbindungHerstellen");kann ich in der Einzelschrittverfolgung sehen, dass der Funktionsname ungültig ist, er gibt also immer false zurück.
Da ich, wie gesagt, gerade erst angefangen habe, mich um dynamisch geladene DLLS zu kümmern, stehe ich etwas auf dem Schlauch und bin ratlos. Bitte ädert das.
Danke,
Oliver.
P.S.: Vielleicht zur Ergänzung: Die Datei Datenbankverwaltung.dll befindet sich im gleichen Verzeichnis wie die Projekt.bpr - Datei und sieht so aus:
static TADOConnection* verbindung; extern "C" __declspec(dllexport) TADOConnection* verbindungHerstellen(String dbname); extern "C" __declspec(dllexport) void verbindungSchliessen(); int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved) { return 1; } TADOConnection* verbindungHerstellen(String dbname) { if (verbindung == NULL) { try { TComponent *Owner = FindGlobalComponent("Datenbankverwaltung"); verbindung = new TADOConnection(Owner); verbindung->ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" "User ID=Admin;" "Data Source=Datenbank\\"+dbname+".mdb;" "Mode=Share Deny None;" "Extended Properties=\"\";" "Jet OLEDB:System database=\"\";" "Jet OLEDB:Registry Path=\"\";" "Jet OLEDB:Database Password=\"\";" "Jet OLEDB:Engine Type=5;" "Jet OLEDB:Database Locking Mode=1;" "Jet OLEDB:Global Partial Bulk Ops=2;" "Jet OLEDB:Global Bulk Transactions=1;" "Jet OLEDB:New Database Password=\"\";" "Jet OLEDB:Create System Database=False;" "Jet OLEDB:Encrypt Database=False;" "Jet OLEDB:Don't Copy Locale on Compact=False;" "Jet OLEDB:Compact Without Replica Repair=False;" "Jet OLEDB:SFP=False"; verbindung->Open(); return verbindung; } catch(Exception *ex) { return NULL; } } else return verbindung; } void verbindungSchliessen() { verbindung->Close(); }
-
Wenns denn wahr wäre, wäre ich froh
Warum sollte es nicht war sein. Solange die DLL im gleichen Ordner wie die EXE ist wird sie gefunden.
String sollte in DLL's nicht als Übergabe oder Rückgabe Parameter genutzt werden, ausgenommen alle beteilitgen Programme includen die Sh.Memory
-
Hi
Also zu Problem eins kann ich leider nichts beitragen. (Habe mich auch erst seit kurzem damit beschäftigt).
Zu zwei, wenn die Funktion über extern "C" exportiert wird, wird glaub ich immer ein Unterstrich _ dem Funktionsnamen vorangestellt. Kannst ja mal mit Dependency Walker die DLL anschauen, damit sollte man dies relative schnell sehen.
MfG Stephan
-
Hallo und danke erst einmal.
Natürlich ist es soweit klar, dass er die dll findet, wenn sie in dem Verzeichnis der *.exe ist, doch es ist egal, welchen Namen ich angebe, er gibt immer true zurück, auch, wenn ich Blah.dll inkludieren will, die nicht da ist...
Zu dem anderen Problem:
Danke auch dir, doch ich habe mir das "Unterstrich-Problem" auch angeschaut und ausprobiert, es ändert nichts. Die Hilfe auf einschlägigen Seiten ist ein wenig merkwürdig, ich fand folgenden Text:// Addresse der Funktion "Addiere" in der DLL herausfinden
// Falls die Funktion nicht gefunden wird, einfach vor den
// Funktionsnamen ein "_" setzen
// Bsp.: statt "Addiere", "_Addiere" verwenden
DllFunktion = (IMPFUNC)GetProcAddress(DllInstance, "Addiere");Jemand eine weitere Idee?
Oliver.
-
Hallo zusammen
Hast schon mit Dependency Walker oder ähnliches nachgeschaut ob überhaupt eine Funktion exportiert wird, bzw wie der Funktionsname aussieht?
@Christian211
Kannst du noch etwas zum Thema Strings und DLLs bzw dem Sh.Memory sagen?
MfG Stephan
-
...sagt mir ehrlich gesagt nichts...
Ich werde mich mal schlau machen, was das ist.
Danke dir.
Das String-Problem ist für mich zumindest - denke ich mal - zweitrangig, da es wahrscheinlich die Probleme nicht erklärt, oder liege ich da so falsch?
Oliver.
-
Hallo StephanK,
hier der - vermutlich interessante - Teil des Dependency Walkers...
Es gibt, do wie ich das sehe, zwei oder drei Funktionen:
_verbindungSchliessen
_verbindungHerstellen
___CPPdebugHookAnsonsten steht dort viel Kram, den ich nicht deuten kann...
Zwei Warnungen habe ich erhalten, die aber glaube ich unwichtig sind.
Warning: At least one delay-load dependency module was not found.
Warning: At least one module has an unresolved import due to a missing export function in a delay-load dependent module.Zumindest sind die Funktionsnamen, wie du erwartetest, mit einem vorgestellten Unterstrich versehen...
Oliver.
-
Kannst du noch etwas zum Thema Strings und DLLs bzw dem Sh.Memory sagen?
//--------------------------------------------------------------------------- // Wichtiger Hinweis zur DLL-Speicherverwaltung, falls die DLL die statische // Version der Laufzeitbibliothek (RTL) verwendet: // // Wenn die DLL Funktionen exportiert, die String-Objekte (oder Strukturen/ // Klassen, die verschachtelte Strings enthalten) als Parameter oder Funktionsergebnisse übergibt, // muss die Bibliothek MEMMGR.LIB im DLL-Projekt und anderen Projekten, // die die DLL verwenden, vorhanden sein. Sie benötigen MEMMGR.LIB auch dann, // wenn andere Projekte, die die DLL verwenden, new- oder delete-Operationen // auf Klassen anwenden, die nicht von TObject abgeleitet sind und die aus der DLL exportiert // werden. Durch das Hinzufügen von MEMMGR.LIB wird die DLL und deren aufrufende EXEs // angewiesen, BORLNDMM.DLL als Speicherverwaltung zu benutzen. In diesem Fall // sollte die Datei BORLNDMM.DLL zusammen mit der DLL weitergegeben werden. // // Um die Verwendung von BORLNDMM.DLL, zu vermeiden, sollten String-Informationen als "char *" oder // ShortString-Parameter weitergegeben werden. // // Falls die DLL die dynamische Version der RTL verwendet, müssen Sie // MEMMGR.LIB nicht explizit angeben. //---------------------------------------------------------------------------