[winapi] biblioteki dll

0

Witam wszystkich:]
Mam problem z importowaniem funkcji do programu z biblioteki dll, ucze się od nie dawna winapi więc prosze o wyrozumiałość. Program kompiluje Dev-C++ niby wszystko ok ale dll'ka nie startuje, nie wiem dlaczego.

Kod programu:

#include <windows.h>

HINSTANCE hinstDLL;

LRESULT CALLBACK NaszaProcedura(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
		
		switch (message) {
  case WM_CREATE:
hinstDLL = LoadLibrary((LPCTSTR) "dll.dll");
      break;

     case WM_DESTROY:

		 FreeLibrary(hinstDLL);
			 PostQuitMessage(0);
			 	 break;
		default:
				return (DefWindowProc(hWnd, message, wParam, lParam));
		}
}


int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{

HWND hOkno; //uchwyt okna
MSG message; //struktura komunikatów
WNDCLASS okno; //klasa okna

okno.hInstance = hInstance; //uchwyt instancji
okno.lpszClassName = "klasa główna"; //nazwa klasy okna
okno.lpfnWndProc = NaszaProcedura;
okno.lpszMenuName = NULL; //brak menu
okno.style = 0; //standardowe okno
okno.hIcon = LoadIcon (NULL, IDI_APPLICATION); //standardowa ikona
okno.hCursor = LoadCursor (NULL, IDC_ARROW); //standardowy kursor
okno.hbrBackground = (HBRUSH)COLOR_WINDOW; //czarny kolor
okno.cbClsExtra = 0; //brak przydziału dodatkowej pamieci dla klasy okna
okno.cbWndExtra = 0; //brak przydziału dodatkowej pamieci okna

if(!RegisterClass (&okno)) return 0; //rejestracja klasy okna

hOkno = CreateWindow ("klasa główna", "Program", WS_OVERLAPPEDWINDOW, 100,100,200,100, NULL, NULL, hInstance, NULL); //utworzenie okna
ShowWindow(hOkno, SW_SHOW); //wyświetlenie okna na ekranie
UpdateWindow(hOkno);
 
while (GetMessage(&message, NULL, 0, 0)) {
	  TranslateMessage (&message);
	  DispatchMessage (&message);
}

}

Kod bibliteki dll (dll.cpp):

#include "dll.h"
#include <windows.h>

DWORD dTimeIdle=0;
static HHOOK hhookKeyb;

DLLIMPORT LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam);

BOOL WINAPI DllMain(HINSTANCE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved) {
	static HINSTANCE hinstDLL = hModule;
	static HOOKPROC hkprcKeyb;


	switch(ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:

		MessageBox(NULL, "Ładowanie biblioteki", "Info", MB_OK);
		hhookKeyb = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, hinstDLL, 0);
		if(!hhookKeyb)
			MessageBox(NULL, "Ustawienie HOOK'a NIE powiodło się", "Info", MB_OK | MB_ICONERROR);
		else
			MessageBox(NULL, "Ustawienie HOOK'a powiodło się", "Info", MB_OK);


		break;

	case DLL_PROCESS_DETACH:

		MessageBox(NULL, "Wyładowywanie biblioteki ;)", "Info", MB_OK);
		
		

		if(!UnhookWindowsHookEx(hhookKeyb))
			MessageBox(NULL, "Usunięcie HOOK'a NIE powiodło się", "Info", MB_OK | MB_ICONERROR);
		else
			MessageBox(NULL, "Usunięcie HOOK'a powiodło się", "Info", MB_OK);


		break;
	}
    return TRUE;
}

//keyboard hook functions


DLLIMPORT LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
	char tab[255];

	if (nCode < 0)  
    return CallNextHookEx(hhookKeyb, nCode, wParam, lParam);

	if((lParam & 0x80000000) == 0)
        return CallNextHookEx(hhookKeyb, nCode, wParam, lParam);

	wsprintf(tab, "%c %x", wParam, wParam);

	MessageBox(NULL, tab, "Wirtualny kod wciśniętego klawisza",MB_OK);

	return CallNextHookEx(hhookKeyb, nCode, wParam, lParam);
	
}

Kod bibliteki dll (dll.h):

#ifndef _DLL_H_
#define _DLL_H_

#if BUILDING_DLL
# define DLLIMPORT __declspec (dllexport)
#else /* Not BUILDING_DLL */
# define DLLIMPORT __declspec (dllimport)
#endif /* Not BUILDING_DLL */


class DLLIMPORT DllClass
{
  public:
    DllClass();
    virtual ~DllClass(void);

  private:

};


#endif /* _DLL_H_ */
0

Hym..
u mnie po zmianie paru szczegółów (inny kompilator) - działa ( jako tako)...

Tu jest chyba błąd , mój kompilator tego nie trawi :

#ifndef _DLL_H_
#define _DLL_H_

#if BUILDING_DLL     // <<<====Tu
# define DLLIMPORT __declspec (dllexport)
#else /* Not BUILDING_DLL */
# define DLLIMPORT __declspec (dllimport)
#endif /* Not BUILDING_DLL */

Raczej powinno być :

#ifdef BUILDING_DLL  
..

No ale jeśli jest to plik wygenerowany automatycznie to niech tak będzie jak było...
widocznie BUILDING_DLL jest definiowane w ten sposób:

#define BUILDING_DLL  1     // albo jakaś tam wartość

Właściwie jeśli udała się kompilacja to kod który podałeś powinien działac ..

Ładując dynamicznie biblioteki sprawdzaj wynik zwracany przez fun "LoadLibrary" .
Dowiesz się czy biblioteka została załadowana , to ułatwia poszukiwanie błędów .

Np:

...
..
                switch (message) {
  case WM_CREATE:
hinstDLL = LoadLibrary((LPCTSTR) "dll.dll");

     if(NULL == hinstDLL)
     {
        MessageBox(NULL,"dll.dll", "Błąd ładowania .dll",MB_OK);
     }
...
...
0

Kompilacja udaje sie bez błędnie lecz kod zawarty w dll'ce nie zostaje wykonany przy uruchomieniu programu, a instrukcja warunkowa nie wyświetla błędu...

0

? .. Jaką masz wersję Dev , sprawdzę jak to idzie na Dev...

0

Nie musisz mi dziękować :P Ale na poważnie to masz problem banalny. Też kiedyś kombinowałem co jest nie tak. Jeśli piszesz w Dev-C++ to dodawaj do każdej funkcji klasy, lub po prostu wszystko weź ogarnij w extern "C". Biblioteki pisane w c++ moją jeszcze przedrostki wstawiane przed funkcjami i dlatego potem są problemu. W ten sposób je wyeliminujesz. Gdybyś ten sam kod napisał i skompilował jako C to by chodziło. Jak chcesz używać c++ to dodawaj to co pisałem. Jak to zrobić to proste:

extern "C" {

.... program, funkcje, klasy, metody, zmienne

}

tak jak tutaj np.

/* Replace "dll.h" with the name of your header */
#include "dll.h"
#include <windows.h>

extern "C"
{
DllClass::DllClass()
{

}


DllClass::~DllClass ()
{

}


BOOL APIENTRY DllMain (HINSTANCE hInst     /* Library instance handle. */ ,
                       DWORD reason        /* Reason this function is being called. */ ,
                       LPVOID reserved     /* Not used. */ )
{
    switch (reason)
    {
      case DLL_PROCESS_ATTACH:
           MessageBox(NULL, "Ładowanie biblioteki", "Info", MB_OK);
        break;

      case DLL_PROCESS_DETACH:
        break;

      case DLL_THREAD_ATTACH:
        break;

      case DLL_THREAD_DETACH:
        break;
    }

    /* Returns TRUE on success, FALSE on failure */
    return TRUE;
}

}

i dll.h

#ifndef _DLL_H_
#define _DLL_H_

#if BUILDING_DLL
# define DLLIMPORT __declspec (dllexport)
#else /* Not BUILDING_DLL */
# define DLLIMPORT __declspec (dllimport)
#endif /* Not BUILDING_DLL */

extern "C" {
       
class DLLIMPORT DllClass
{
  public:
    DllClass();
    virtual ~DllClass(void);

  private:

};


}

#endif /* _DLL_H_ */

Jak usuniesz extern "C" lub dllmain nie będzie nim objęte to ci dllmain nie wystartuje.

PS. nie wiem jak z innymi kompilatorami. To jest tylko informacja do Dev-C++

0

Potwierdzam ...przekompilowałem w Dev , sprawdziłem i tak właśnie jest .
Z innymi kompilatorami ? pewnie różnie np .Builder nie sprawia takich problemów.

W zasadzie tworząc biblioteki deklaracje fun. umieszcza się w pliku nagłówkowym
zawierającym odpowiednie definicje .Pozwalają one z pomocą preprocesora
utworzyć bibliotekę w konwencji wywołań C nawet jeśli projekt jest kompilowany
jako C++ . Następuje po prostu dołączenie w tym przypadku przez cpp deklaracji
extern "C" .
np:

#ifndef __TESTBIB_H
#define __TESTBIB_H
//   Funkcje zawatre w bibliotece

#ifdef __cplusplus
extern "C"{
#endif

int CALLBACK _export  Funkcja_test_dll(void) ;

#ifdef __cplusplus
       }
#endif

#endif

1 użytkowników online, w tym zalogowanych: 0, gości: 1