Dll Import klappt nicht

javaprogger1987

Erfahrenes Mitglied
Hallo!
Ich bin sonst eher im Java-Forum hab aber mal nen Problem mit C-C++ was mich verzweifeln lässt :/
Also die Grundidee ist, in Java mit Keyboard-Hooks arbeiten zu können, um (systemweite) Hotkeys benutzen zu können..
Daher hab ich mich mal ein bischen mit der Sache beschäftigt, es scheitert aber schon am arbeiten mit den DLL's.. Dazu vllt ein paar Code Auschnitte:
Code:
JNIEXPORT jboolean JNICALL Java_keyhook_KeyHookMain_loadHooks
 (JNIEnv *env, jobject clazz)
 {
         InstallHook = NULL;
         UninstallHook = NULL;
         
         HINSTANCE hDll = LoadLibrary("jnikeyhook.dll");
         if ( hDll = NULL )
            return (jboolean)FALSE;
         
         InstallHook = (MYFUNC) GetProcAddress( hDll, "InstallHook" );
         if ( InstallHook = NULL )
            return (jboolean)FALSE;

         UninstallHook = (MYFUNC) GetProcAddress( hDll, "UninstallHook" );
         if ( UninstallHook = NULL )
            (jboolean)FALSE;
            
         Out = (MYFUNC) GetProcAddress( hDll, "Out" );
         //Out(); <- Geht nicht
         
         FreeLibrary( hDll );
         
         return (jboolean)TRUE;
 }

Das ist die Funktion von Java aus aufgerufen wird.. Das klappt auch schon, allerdings stürtzt alles ab sobald ich die markierte Zeite reinschreibe.. Da ich dachte es läge an den Hooks habe ich extra schon mal die Testfunktion Out geschrieben, das geht aber trotzdem nicht.
Wenn ich den Funktionsaufruf von Out rausstreiche läuft die Methode ohne Probleme ab, es true zurückgegeben und es erscheint 6-Mal (?) ein Dialog der in untenstehender DllMain erzeugt wird..

Header:
Code:
typedef BOOL (*MYFUNC)(void);

MYFUNC InstallHook;
MYFUNC UninstallHook;
MYFUNC Out;

Und dann die andere Dll (jnikeyhook.dll):
Code:
// Globale Variablen
HHOOK g_hKeyHook SHARED = NULL;    // Handle unseres Hooks (als "shared" Deklariert)
HINSTANCE g_hInst SHARED = NULL;     // Handle der DLL selbst

BOOL APIENTRY DllMain (HINSTANCE hInst     /* Library instance handle. */ ,
                       DWORD reason        /* Reason this function is being called. */ ,
                       LPVOID reserved     /* Not used. */ )
{
    MessageBox(NULL, "Entry!", "Out", MB_OK);
    g_hInst = hInst;
    return TRUE;
}
.
.
.
DLLIMPORT BOOL Out()
{
    MessageBox(NULL, "TEST", "TEST", MB_OK);
    return TRUE;
}
Header:
Code:
#ifndef _DLL_H_
#define _DLL_H_

#include <windows.h>

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

// zur Deklaration von Variablen innerhalb eines "shared data segment"
#define SHARED __attribute__((section(".shr"), shared))

DLLIMPORT BOOL Out();
DLLIMPORT BOOL InstallHook();
DLLIMPORT BOOL UninstallHook();

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

#endif /* _DLL_H_ */

Wär echt super wenn hier jemand Rat wüsste :)
Danke schonmal

Gruß
Tobias
 
Zuletzt bearbeitet:
Direkt weiss ich keinen Rat, vermute aber, das Out an der Stelle NULL ist.

Was mich viel mehr stört sind deine If-Abfragen mit nur einem Gleichzeichen. Dadurch setzt du die Variable bei der Prüfung auf NULL:

if ( hDll = NULL )

Das sollte doch

if ( hDll == NULL )

sein.

Andererseits wundert mich dann viel mehr, dass dein Programm überhaupt bis zu der Out-Stelle kommt, es müsste eigentlich bei der ersten falschen If-Abfrage rausspringen.
 
Ach du meine Güte :-(
Das ist natürlich ein ziemlich dummer Fehler, jetzt funktioniert es auch, vielen Dank :)
Warum der bei den if-Abfragen nicht abgebrochen hat ist mir allerdings auch schleierhaft..

Gruß
Tobias
 
Hi.
Endurion hat gesagt.:
Andererseits wundert mich dann viel mehr, dass dein Programm überhaupt bis zu der Out-Stelle kommt, es müsste eigentlich bei der ersten falschen If-Abfrage rausspringen.
Warum? NULL entspricht doch dem Wahrheitswert false und somit wird die if-Anweisung niemals ausgeführt.

Gruß
 
So ich noch mal :)
Das oben beschriebene Problem habe ich nun nicht mehr, die KeyboardProc Callback Funktion wird auch aufgerufen.
Mein Problem ist aber folgendes:
Wenn ich eine Taste gedrückt halte wird die KeyboardProc Funktion immer wieder aufgerufen.. Wie kommt das?
Kann ich aus lParam oder wParam vllt irgendwie ermitteln, ob die Taste gedrückt oder losgelassen wurde?

Und dann noch eine Frage:
Code:
if ((GetAsyncKeyState(VK_CONTROL) & 0x8000) && wParam == 'Q')
klappt schon super - nur wenn ich STRG+Q drücke wird die Bedingung wahr, bei
Code:
if ((lParam & KF_ALTDOWN) == 0) && wParam == 'Q')
ist die Bedingung jedoch immer wahr wenn ich Q drücke.. Ist die Bedingung für gedrückte ALT Taste falsch?

Vielen Dank
Gruß
Tobias
 
javaprogger1987 hat gesagt.:
So ich noch mal :)
Das oben beschriebene Problem habe ich nun nicht mehr, die KeyboardProc Callback Funktion wird auch aufgerufen.
Mein Problem ist aber folgendes:
Wenn ich eine Taste gedrückt halte wird die KeyboardProc Funktion immer wieder aufgerufen.. Wie kommt das?
Naja, du hälst die Taste gedrückt. ;) Dann werden auch weiter die Ereignisse generiert und die Funktion wird aufgerufen.
Kann ich aus lParam oder wParam vllt irgendwie ermitteln, ob die Taste gedrückt oder losgelassen wurde?
Kannst du. (siehe http://msdn.microsoft.com/library/e...asp?frame=true#_win32_Keystroke_Message_Flags) Du mußt nur das "Previous Key-State Flag" vom lParam prüfen.

Und dann noch eine Frage:
Code:
if ((GetAsyncKeyState(VK_CONTROL) & 0x8000) && wParam == 'Q')
klappt schon super - nur wenn ich STRG+Q drücke wird die Bedingung wahr, bei
Code:
if ((lParam & KF_ALTDOWN) == 0) && wParam == 'Q')
ist die Bedingung jedoch immer wahr wenn ich Q drücke.. Ist die Bedingung für gedrückte ALT Taste falsch?
Ja. Irgendwie solltest du dir mal die Auswertung von boolschen Ausdrücken und Bitoperatoren anschauen (das ist aber in Java nix anderes). In der ersten Bedingung machst du das ja auch besser.:confused:
C:
if ((lParam & KF_ALTDOWN) ...
Gruß
 
Ja ich hab mich davor bis jetzt immer gedrückt ;) Aber wie es aussieht ist das in C/C++ noch ne Ecke wichtiger als in Java..
Also mal sehen ob ich das verstanden habe:
Code:
if ((GetAsyncKeyState(VK_CONTROL) & 0x8000)
verknüpft das Ergebnis von GetAsyncKeyState mit dem Hex Wert 8000 (16 Bit - oberstes 1)per AND und guckt ob das Ergebnis ungleich null ist?
D.h. GetAsyncKeyState liefert eine 2Byte Zahl zurück, bei der das oberste Bit gesetzt ist, wenn die Taste gedrückt ist?

Für die andere Bedingung hieße das ja dann folgendes:
Code:
if ((lParam & KF_ALTDOWN)
KF_ALTDOWN müsste MSDN zufolge dann den Wert 0x20000000 haben oder? Weil an Bit-Position 29 steht ja das ensprechende Bit, welches für ALT gesetzt ist..

P.S: Da ich das noch nicht ganz gerafft hab, hab ich die Bedinung einfach kopiert - war anscheinend in der Quelle auch falsch -.- Das kommt von der Faulheit ;)

Gruß
 
javaprogger1987 hat gesagt.:
Also mal sehen ob ich das verstanden habe:
Code:
if ((GetAsyncKeyState(VK_CONTROL) & 0x8000)
verknüpft das Ergebnis von GetAsyncKeyState mit dem Hex Wert 8000 (16 Bit - oberstes 1)per AND und guckt ob das Ergebnis ungleich null ist?
Ja, im Prinzip ist das richtig. Man kann natürlich auch explizit != 0 hinschreiben, so kann man es dann leichter verstehen.
javaprogger1987 hat gesagt.:
D.h. GetAsyncKeyState liefert eine 2Byte Zahl zurück, bei der das oberste Bit gesetzt ist, wenn die Taste gedrückt ist?
Ja.
javaprogger1987 hat gesagt.:
Für die andere Bedingung hieße das ja dann folgendes:
Code:
if ((lParam & KF_ALTDOWN)
KF_ALTDOWN müsste MSDN zufolge dann den Wert 0x20000000 haben oder? Weil an Bit-Position 29 steht ja das ensprechende Bit, welches für ALT gesetzt ist..
Nicht ganz. Merkwürdigerweise ist KF_ALTDOWN auf 0x2000 == 8192 gesetzt so das das 13. Bit geschaltet ist. Es ist anscheinend so das die Flags nur für das höherwertige Byte von lParam gelten so das man noch zusätzlich um 16 Bits shiften muss. Ich hätte allerdings dazu eine eindeutige Aussage auf der MSDN Seite erwartet habe aber nichts dergleichen gefunden.
C:
if (lParam & (KF_ALTDOWN << 16)...

Gruß
 
Okay vielen vielen Dank für die Hilfe :) Ich hoffe mal ich hab das nun verstanden..
Eine allerletzte Frage hab ich aber doch noch:
Wieso benutzt man GetAsyncKeyState statt GetKeyState?
Laut MSDN liefert GetAsyncKeyState den aktuellen Status der Taste zurück, GetKeyState den der Taste als das Ereignis auftrat.. Ist es dann nicht sinnvoller GetKeyState zu verwenden - oder läuft das so schnell ab, dass beide immer den gleichen Wert liefern würden?

Gruß
 
Ich würde auch sagen das es besser wäre GetKeyState für dein Vorhaben zu verwenden. Es kann natürlich sonst passieren, dass ein Q ohne Strg gedrückt wurde allerdings GetAsyncState dann doch Strg als gedrückt meldet weil inzwischen der Benutzer Strg hält. Das ist dann so eine Art Race-Condition - man müßte ja schon wirklich sehr schnell sein bzw. der Rechner ziemlich ausgelastet so das das Ereignis nicht sofort bearbeitet werden kann.

Gruß
 
Zurück