Problem beim DLL-Einbinden und GetProcAddress()

Von: , Frage gestellt am Mi, 8. Aug 2007

Moin!

Ich verzweifle am korrekten Einbinden einer DLL. Obwohl ich mich, denke ich, an die zahlreichen Beispiele im Internet gehalten habe, klappt es einfach nicht. Wäre nett, wenn mal jemand drüber gucken könnte.

Und bitte nicht auf Google verweisen, da habe ich nun schon etliche Stunden erfolglos investiert...

Das Einbinden per LoadLibrary() klappt, jedoch liefert GetProcAddress() kein gültiges Handle. GetLastError() liefert 127 (The specified procedure could not be found) zurück.

myDLL.h :

#ifdef MYDLL_EXPORTS
#define MYDLL_API __declspec(dllexport)
#else
#define MYDLL_API __declspec(dllimport)
#endif
MYDLL_API void ScreenShotWholeDesktop(void);


myDLL.cpp :
#include "stdafx.h"
#include "myDLL.h"
BOOL APIENTRY DllMain( HANDLE hModule, 
DWORD  ul_reason_for_call, 
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
MYDLL_API void ScreenShotWholeDesktop(void) {
//--------------------------------------------------------------------------------------------------------------------------
//__declspec(dllexport) void _cdecl ScreenShotWholeDesktop(void) {
//--------------------------------------------------------------------------------------------------------------------------
int     nWidth  = GetSystemMetrics(SM_CXSCREEN);
int     nHeight = GetSystemMetrics(SM_CYSCREEN);
HWND    hWnd    = ::GetDesktopWindow();
HDC     hdc     = ::GetDC(hWnd);
HDC     memDC   = ::CreateCompatibleDC(hdc);
HBITMAP hbm     = ::CreateCompatibleBitmap(hdc, nWidth, nHeight);
HBITMAP hbmOld  = (HBITMAP)::SelectObject(memDC, hbm);
::BitBlt(memDC, 0, 0, nWidth, nHeight, hdc, 0, 0, SRCCOPY);
BITMAPINFO bmi;
ZeroMemory(&bmi, sizeof(bmi));
bmi.bmiHeader.biSize         = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth        = nWidth;
bmi.bmiHeader.biHeight       = nHeight;
bmi.bmiHeader.biBitCount     = 24;
bmi.bmiHeader.biPlanes       = 1;
bmi.bmiHeader.biCompression  = BI_RGB;
bmi.bmiHeader.biSizeImage    = 32 * nWidth * nHeight / 8;
BYTE *pbBits = new BYTE[bmi.bmiHeader.biSizeImage];
::GetDIBits( memDC, 
hbm,
0,
bmi.bmiHeader.biHeight,
pbBits,
&bmi,
DIB_RGB_COLORS );
BITMAPFILEHEADER bfh;
bfh.bfType      = ('M' << 8) + 'B';
bfh.bfSize      = sizeof(BITMAPFILEHEADER)  +
bmi.bmiHeader.biSizeImage +
sizeof(BITMAPINFOHEADER); 
bfh.bfReserved1 = 0;
bfh.bfReserved2 = 0;
bfh.bfOffBits   = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
SetDIBits(memDC,hbm,0,bmi.bmiHeader.biHeight,pbBits,&bmi,DIB_RGB_COLORS);
//  StretchBlt(*hDC, 0, 0, WinSizeX,WinSizeY,memDC, 0, 0,WinSizeX/2,WinSizeY/2,SRCCOPY);
//  BitBlt(*hDC, 0, 0, GetSystemMetrics(SM_CXSCREEN)-1,GetSystemMetrics(SM_CYSCREEN)-1,memDC, 0, 0, SRCCOPY);
HANDLE hfile = CreateFile( "__TMP__SCRNSHOT__2357__.BMP",
GENERIC_WRITE,
0,
0,
CREATE_ALWAYS,
0,
0 ); 
if(hfile==INVALID_HANDLE_VALUE) {
MessageBox(NULL,"Datei konnte nicht erzeugt werden!",NULL,MB_OK);
}
DWORD dwWritten;
WriteFile(hfile,&bfh,           sizeof(bfh),               &dwWritten, NULL); 
WriteFile(hfile,&bmi.bmiHeader, sizeof(BITMAPINFOHEADER),  &dwWritten, NULL); 
WriteFile(hfile,pbBits,         bmi.bmiHeader.biSizeImage, &dwWritten, NULL); 
CloseHandle(hfile); 
::SelectObject(memDC, hbmOld);
::DeleteDC(memDC);
::ReleaseDC(hWnd,hdc); 
::DeleteObject(hbm);
delete[] pbBits;
return;
}


testDLL.cpp :
#include "stdafx.h"
#include "..\\myDLL.h"
typedef void (*DLLFUNC)(void);
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow) {
//
HMODULE hDLL = LoadLibrary("..\\debug\\myDLL.dll");
DLLFUNC pfnDllScreenShotWholeDesktop = NULL;
if(hDLL==NULL) {
MessageBox(NULL,"LoadLibrary NICHT erfolgreich!",NULL,MB_OK);
}
pfnDllScreenShotWholeDesktop = (DLLFUNC)GetProcAddress((HINSTANCE)hDLL,"ScreenShotWholeDesktop");
if(pfnDllScreenShotWholeDesktop==NULL) {
MessageBox(NULL,"GetProcAddress NICHT erfolgreich!",NULL,MB_OK);
char sTmp[10]={0};
wsprintf(sTmp,"Error: %i",GetLastError());
MessageBox(NULL,sTmp,NULL,MB_OK);
}
//pfnDllScreenShotWholeDesktop();
FreeLibrary(hDLL);
return 0;
}


Im Voraus schonmal vielen Dank!

Gruß Matze

3 Antworten zu dieser Frage

  1. Antwort von nach 4 Stunden 0 hilfreich
    Re: Problem beim DLL-Einbinden und GetProcAddress(

    Hi,

    ich will nicht sagen, daß ich große Ahnung von DLL_Programmierung habe.

    Also stelle ich mal eine (vielleicht dumme) Frage:

    Deine DLL-Header Datei ist : myDLL.h :

    #ifdef MYDLL_EXPORTS
    #define MYDLL_API __declspec(dllexport)
    #else
    #define MYDLL_API __declspec(dllimport)
    #endif
    MYDLL_API void ScreenShotWholeDesktop(void);
    

    Das heißt doch, sie exportiert nur dann die Funktion korrekt, wenn
    das Symbol MYDLL_EXPORTS existiert.
    Zur Frage: Sollte das Symbol dann nicht irgendwann mal mit
    "#define MYDLL_EXPORTS" gesetzt werden ?

    Nun ja, wie gesagt meine Ahnung in dem Bereich ist begrenzt :-)

    Wünsche noch viel Erfolg,
    Hendrik

    • Antwort von nach 4 Stunden 0 hilfreich
      Re^2: Problem beim DLL-Einbinden und GetProcAddres

      Hallo!

      Die von dir angesprochene Stelle ist vom VS erzeugt worden und funktioniert. Ich habe mich allerdings auch gefragt, ob das define denn auch wirklich immer definiert ist, insofern war das entweder keine dumme Frage oder wir sind beide nicht die hellsten ;-)

      Ich habe den Fehler (?!) allerdings eben mithilfe eines Kollegen gefunden.
      Man muss in der Header-Datei vor die Deklaration ein 'extern "C"' setzen. Dies hatte ich schon vorher versucht, bin allerdings immer gescheitert. Als wir es dann nochmal mit geschweiften Klammern versuchten, hat's geklappt.

      So muss es aussehen:

      extern "C" { MYDLL_API void ScreenShotWholeDesktop(void); }
      


      Trotzdem danke!

      Gruß Matze

      • Antwort von nach 6 Stunden 0 hilfreich
        Re^3: Problem beim DLL-Einbinden und GetProcAddres

        Hallo! Man muss in der Header-Datei vor die Deklaration ein 'extern
        "C"' setzen.
        Yup, sonst macht das Ding typsicheres linken und das hat mit C-Style
        nichts zu tun. So muss es aussehen:
        Wenn du es ganz richtig machen willst dann gehört noch was dazu
        oder besser, dann kannst du es ohne Änderungen auch in C-Quellen
        benutzen.

        #ifdef __cplusplus
        extern "C" {
        #endif
        /* hier kommen jetzt alle Definitionen die C-Style sind */
        MYDLL_API void ScreenShotWholeDesktop(void);
        #ifdef __cplusplus
        }
        #endif
        


        Gruß
        Stefan

Keine passende Antwort gefunden? Jetzt eigene Frage stellen!