nach dll-funktions aufruf fehler
-
die meldung lautet
The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared whit one calling converention with a function declared with one calling converention with a function pointer with a different calling convention.
wenn ich die richtig verstehe mag er meine funktions deklaration net so oda ?
im hauptprogramm
typedef bool (*MYPROC)(HWND,WORD,LPCSTR,LPCSTR); ... bool ConfigDlg(HWND hWnd,char* instr,char* out) { MYPROC ProcAdd; HINSTANCE hinstLib; BOOL fFreeResult, fRunTimeLinkSuccess = FALSE; char* ConfOut=new char; SWORD dw=NULL; hinstLib = LoadLibrary("sopdc"); // If the handle is valid, try to get the function address. if (hinstLib != NULL) { ProcAdd = (MYPROC) GetProcAddress(hinstLib,"ConfigDSN"); dw=GetLastError(); if (NULL != ProcAdd) { fRunTimeLinkSuccess = TRUE; (ProcAdd)(hWnd,sizeof(instr),(char*)instr,"");//,(char*)ConfOut,dw); ConfOut[dw]='\0'; sprintf((char*)out,"DSN=%s;",ConfOut); } else return 0; } else return 0; fFreeResult = FreeLibrary(hinstLib); return 1; } ...
in der dll
BOOL INSTAPI ConfigDSN(HWND hWnd, WORD fRequest, LPCSTR lpszDriver, LPCSTR lpszAttributes)//name des treibers { // Die Funktion gibt Wert zurück ob der User eine Benutzer oder System DSN // anlegen möchte SQLGetConfigMode(&modus); // Setzt den DSN-Pfad zusammen und speichert Ihn in der Struktur getdsnname((char *)lpszAttributes,"DSN=",global_werte.lDestination, sizeof(global_werte.lDestination)); switch(modus) { case ODBC_USER_DSN: global_regkey.modus=HKEY_CURRENT_USER; break; case ODBC_SYSTEM_DSN: HKEY hk; long res; res=RegCreateKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\ODBC"), 0, 0, REG_OPTION_NON_VOLATILE, KEY_WRITE, 0, &hk, 0); if(res!=ERROR_SUCCESS) { MessageBox(0,"You must be administrator to create System-DSN!",DBMS_NAME,0); return 0; } global_regkey.modus=HKEY_LOCAL_MACHINE; break; case ODBC_BOTH_DSN: MessageBox(0,"No BOTH_DSN Supported","OPDC",MB_OK); break; default: MessageBox(0,"Unknown mode",0,0); break; }; switch (fRequest) { case ODBC_CONFIG_DSN: { add_mod=0; break; } case ODBC_ADD_DSN: { add_mod=1; break; } case ODBC_REMOVE_DSN: { SQLRemoveDSNFromIni(global_werte.lDestination); return TRUE; } default: return FALSE; } if(fRequest!=ODBC_REMOVE_DSN) { HWND hw; InitStruct(); hw = FindWindow("#32770","ODBC-Datenquellen-Administrator"); DialogBox(s_hModule,MAKEINTRESOURCE(IDD_DIALOG1),hw,Dlg_Proc); } return TRUE; }
könnte mir da bitte jemand helfen ?
danke euch
-
hast du deine funktionen richtig deklariert ?
sollte etwa so aussehen:
#ifdef __cplusplus #define EXPORT extern "C" __declspec (dllexport) #else #define EXPORT __declspec (dllexport) #endif
das EXPORT muss dann natürlich in die funktionsdeklaration mit rein !
rocknix ///
-
Nimm entweder das INSTAPI raus, oder setz es in dein typedef
typedef bool (INSTAPI *MYPROC)(HWND,WORD,LPCSTR,LPCSTR);
BTW: Kann mir mal jemand erklären, warum soviele Leute ihre DLL Funktionen als __stdcall Funktion deklarieren (INSTAPI ist auch __stdcall). Hat das irgendeinen weiteren Sinn? Sollte man das machen?
-
den export habe ich in einer .def datei gesetzt
anders kenn ichs leider net.def
LIBRARY setupdll
EXPORTSConfigDSN @1
-
Lies nochmal meinen Beitrag. :p
-
hab dank jetzt gehts
habs mit __stdcall gemacht und alles läuft noch
-
Jaja, mit __stdcall läufts auch ohne Probleme. Ich verstehe nur nicht warum man das benutzt, wenns auch ohne bestens funktioniert?
-
kein plan ich kenn mich net genug damit aus ums dir zu sagen
des war irgendwie vorgegeben..
naja es geht nu alles dafür danke ich dir
-
Ich bin mir nicht sicher, aber ich vermute folgendes:
_stdcall bedeutet ja die Parameter von links nach rechts auf den stack zu schieben. Daher muss der "rechteste" Parameter zuerst abgefragt werden. Bei _cdecl ist es genau andersherum. Darum kann man mit _cdecl variable Parameterlisten implementieren.
Delphi kann AFAIK nur _stdcall Funktionen aufrufen, keine _cdecl. Deswegen kann man in Delphi wsprintf nicht verwenden, weil das eine der wenigen _cdecl Funktionen der WindowsDLLs ist.
Das ist nur eine Vermutung, erscheint mir aber plausibel.
-
Ne, bei beiden (_cdecl und __stdcall) werden die Parameter von rechts nach links gelesen.
-
Stimmt.
Der Unterschied besteht darin, wer verantwortlich ist die Parameter vom Stack zu holen.
Bei _stdcall ist die aufgerufene Funktion zuständig, bei _cdecl der Aufrufer.Kommt aber aufs selbe raus, weil ja bei variablen Parameterlisten die Größe und Anzahl der Parameter erst zur Laufzeit bekannt sind (in der Funktion).
Beim Aufrufer sind die Parameter dagegen schon zur Compilezeit bekannt.[ Dieser Beitrag wurde am 21.01.2003 um 16:44 Uhr von cd9000 editiert. ]