Laden einer C-DLL - Aurfruf einer Funktion
-
Hallo,
ich schreibe gerade ein kleines Konsolen-Programm, welches auf ein DLL eines Drittanbieters zugreifen soll.
Ich dachte eigentlich das mein Code nicht unbedingt ganz sauber aber ok ist, leider stürtzt die DLL scheinbar beim Aufruf einer der Funktionen ab.
Doku Anbieter:
Die Schnittstelle der DLL exportiert folgende Funktionen:
#define DLLCALL(typ) __declspec(dllexport) typ _cdecl
extern "C" {
DLLCALL(int) initXML(void);
DLLCALL(int) initDB(char *strCon);
DLLCALL(int) doXML(char *inStream, char *outStream);
}Der Aufruf der initXML() und initDB() funktioniert auch noch (sieht man im Logfile der DLL). Beim Aufruf der doXML() Stürtzt die DLL ab. Die Frage ist eigentlich ob ich schon beim Laden oder importieren der Funktionen einen Fehler mache.
int _tmain(int argc, _TCHAR* argv[]) { char* request; char* answer; typedef int (*ptrinitXML)(void); typedef int (*ptrinitDB)(char *strCon); typedef int (*ptrdoXML)(char *inStream, char *outStream); ptrinitXML MinitXML; ptrinitDB MinitDB; ptrdoXML MdoXML; HINSTANCE DLL = NULL; DLL = LoadLibrary(_T("init.dll")); request = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?><REQUEST><COMMAND>Find</COMMAND><DATA><KUNDE>Meier</KUNDE><LAND>DE</LAND></DATA></REQUEST>"; if (DLL) { MinitXML = (ptrinitXML)GetProcAddress(DLL, "initXML"); MinitDB = (ptrinitDB)GetProcAddress(DLL, "initDB"); MdoXML = (ptrpdoXML)GetProcAddress(DLL, "doXML"); MinitXML(); MinitDB("Driver={Microsoft Access Driver (*.mdb)};Dbq=C:\\test\\test.mdb"); MdoXML(request,answer); FreeLibrary(DLL); } getch(); return 0; }
-
Du hast auf jeden Fall vergessen, Speicher für die Ausgabe zu reservieren - das heißt answer zeigt irgendwo in den RAM (und an der Stelle darfst du mit hoher Wahrscheinlichkeit nichts hinschreiben). Davon abgesehen kommt mir eine Funktion suspekt vor, die ohne Größenkontrolle in ein char-Array schreiben darf (doXML() sollte imho noch eine Angabe bekommen, wieviel Platz sie hinter 'outStream' zur Verfügung hat).
PS: Wenn du der Meinung bist, das Laden der Funktionen ist schon schief gegangen, solltest du die Rückgabewerte der GetProcAdress()-Aufrufe auswerten.
-
Hallo Es muss natürlich heissen:
#define DLLCALL(typ) __declspec(dllexport) typ _cdecl extern "C" { DLLCALL(int) initXML(void); DLLCALL(int) initDB(char *strCon); DLLCALL(int) doXML(char *inStream,int inLen, char *outStream, int *outLen, int maxLen); }int _tmain(int argc, _TCHAR* argv[]) { char* request = new char[1000]; char* answer = new char[1000]; int inLen; int* outLen = new int; typedef int (*ptrinitXML)(void); typedef int (*ptrinitDB)(char *strCon); typedef int (*ptrdoXML)(char *inStream, char *outStream); ptrinitXML MinitXML; ptrinitDB MinitDB; ptrdoXML MdoXML; HINSTANCE DLL = NULL; DLL = LoadLibrary(_T("init.dll")); request = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?><REQUEST><COMMAND>Find</COMMAND><DATA><KUNDE>Meier</KUNDE><LAND>DE</LAND></DATA></REQUEST>"; if (DLL) { MinitXML = (ptrinitXML)GetProcAddress(DLL, "initXML"); MinitDB = (ptrinitDB)GetProcAddress(DLL, "initDB"); MdoXML = (ptrpdoXML)GetProcAddress(DLL, "doXML"); MinitXML(); MinitDB("Driver={Microsoft Access Driver (*.mdb)};Dbq=C:\\test\\test.mdb"); MdoXML(request,1000,answer,outLen,1000); delete []request; delete []answer; FreeLibrary(DLL); } getch(); return 0; }Hatte den Code etwas abgespeckt. Hab alles rausgeschmissen wovon ich dachte es sei nicht relevant.
Kommt aber immer noch nen Fehler. Wie bekomme ich die genau Länge von request.
sizeof() geht da nicht. Wenn request leer bleibt, dann stürzt er nicht ab.
-
Nur mal ein Ausschnitt:
char* request = new char[1000];//reserviert Speicher request = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?><REQUEST><COMMAND>Find</COMMAND><DATA><KUNDE>Meier</KUNDE><LAND>DE</LAND></DATA></REQUEST>";//verbiegt den Zeiger auf's Data-Segment //->Speicherleck delete []request;//delete't Speicherbereiche außerhalb des Heaps //->CrashSo etwas kann nicht gut gehen. Entweder du lässt die Speicherverwaltung für request komplett weg (sowohl das new[] als auch das delete[]) oder du ersetzt die Zuweisung durch einen strcpy()-Aufruf.
Ansonsten: Die Länge kannst du per strlen() bestimmen.
PS: Und ich würde mich bemühen, soweit wie möglich auf nackte Zeiger und char-Arrays zu verzichten.
-
Hallo Danke für die Hilfe, aber noch stimmt was nicht:
int _tmain(int argc, _TCHAR* argv[]) { char* request; char* answer = new char[1000]; int inLen; int* outLen = new int; typedef int (*ptrinitXML)(void); typedef int (*ptrinitDB)(char *strCon); typedef int (*ptrdoXML)(char *inStream, char *outStream); ptrinitXML MinitXML; ptrinitDB MinitDB; ptrdoXML MdoXML; HINSTANCE DLL = NULL; DLL = LoadLibrary(_T("init.dll")); request = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?><REQUEST><COMMAND>Find</COMMAND><DATA><KUNDE>Meier</KUNDE><LAND>DE</LAND></DATA></REQUEST>"; inLen = strlen(request); if (DLL) { MinitXML = (ptrinitXML)GetProcAddress(DLL, "initXML"); MinitDB = (ptrinitDB)GetProcAddress(DLL, "initDB"); MdoXML = (ptrpdoXML)GetProcAddress(DLL, "doXML"); MinitXML(); MinitDB("Driver={Microsoft Access Driver (*.mdb)};Dbq=C:\\test\\test.mdb"); MdoXML(request,inLen,answer,outLen,1000); delete []answer; FreeLibrary(DLL); } getch(); return 0; }Oder hab ich das flasch vertsanden.
-
Durchaus möglich. Aber für weitere Hilfen solltest du mal verraten, was für ein Fehler aufgetreten ist (und wie du es geschafft hast, 5 Parameter an eine Funktion zu übergeben, die nur zwei erwartet ;)).
-
Das Abspecken hab ich natürlich nur für den Post gemacht. Die Funktion hat schon immer alle Parameter bekommen

Fehler wenn ich driekt aufrufe:
DLLKernel.exe hat ein Problem festgestellt und muss beendet werden.
...Standard Windows Meldung halt.
Im VS2005:
Unbehandelte Ausnahme bei 0x10020a54 DLLKernel.exe:
0xC0000005: Zugriffsverletzung beim Schreiben an Position 0x004021ed.