Skip to main content
GameDev.net gamedev.net
🔒 Locked

Calling function pointer from DLL

Started by kamrann Jun 13, 2002 at 6:51 AM 10 replies 700+ views
Original Post
kamrann
kamrann
I''ve never used DLL''s before and don''t really know what I''m doing, but anyway... I downloaded some code for implementing a keyboard hook - I want to catch keypresses even when my app is not the active one. Heres a bit of it: #pragma data_seg("SharedBlock") HHOOK hHook = NULL; int nProcesses = 0; int nKeyPresses = 0; #pragma data_seg() HINSTANCE g_hInstance = NULL; _declspec(dllexport) LRESULT CALLBACK KBHookProc(int nCode, WPARAM wParam, LPARAM lParam) { if(nCode < 0) return CallNextHookEx(hHook, nCode, wParam, lParam); if(lParam & (1 << 31)) nKeyPresses++; return CallNextHookEx(hHook, nCode, wParam, lParam); } The DLL also exported a function to return the number of keypresses. Now I want to change this so that an application defined function is called when the F2 key is pressed. I exported a function SetCallbackFunc(LPCallback pFunc) that the app could use to specify the function it wanted to be called on an F2 press through a function pointer, and changed the above bit of code to do so. However, it doesnt work when my app isn''t active - it still reaches the code above, but calling the function pointer seems to do nothing. I assume this is some problem related to address spaces, but I dont know. Anyone able to tell me what I need to do? Thanks Cameron
Chem0sh
Chem0sh
What exactly does your function do when the user presses F2?

/*=========================================*/
/* Chem0sh */
/* Lead Software Engineer & Tech Support */
/* http://www.eFaces.biz */
/*=========================================*/
/*=========================================// Chem0sh// Lead Software Engineer & Tech Support// http://www.eFaces.biz=========================================*/
kamrann
kamrann
If you mean what is it that I actually want to capture the F2 press for, I need to start a thread which begins data logging from some special hardware, or stop the data logging if its in progress.
If you''re asking what it does at the moment in my testing, I just pass the address of the following function as the callback:


void Action()
{
Beep(800, 500);
}



The callback definitely isn''t being called, since if I put a call to Beep directly in the DLL code, it works as expected.

Any ideas?

Cameron
Chem0sh
Chem0sh
Why not just have the code directly in the dll then? Is there some reason you need to call it thru a function pointer?

You could also monitor for F2 in your dll and when you get it, send a user defined window message to your program (your dll will need to have a handle to your main window. You could either write a seperate function to do this or pass it thru your SetKBHook function). You can then catch that message in your event loop and do whatever you need to.

/*=========================================*/
/* Chem0sh */
/* Lead Software Engineer & Tech Support */
/* http://www.eFaces.biz */
/*=========================================*/
/*=========================================// Chem0sh// Lead Software Engineer & Tech Support// http://www.eFaces.biz=========================================*/
kamrann
kamrann
Because then the DLL code would need to know all about the libraries I''m using for the hardware, and it would get messy. The idea was to have the DLL as generic as possible - just providing the functionality for an app to set up a hook and have a callback when a particular key was pressed.

As for the windows message, I guess I could do that, but speed is reaally important here, so I''d rather not send it through the message system.

Any other ideas why the function pointer call might not work?

Cameron
Chem0sh
Chem0sh
Hmmmm.....I''m out of ideas. Please show the code for:

1) your SetCallbackFunc
2) where you actually call SetCallbackFunc in your main prog
3) and the section where you load SetCallbackFunc from the dll.

Maybe this will jumstart my brain.
/*=========================================// Chem0sh// Lead Software Engineer & Tech Support// http://www.eFaces.biz=========================================*/
kamrann
kamrann

  

// KBHookDLL.cpp


typedef void (*LPF2Callback)();
LPF2Callback g_pfF2Pressed = NULL;

_declspec(dllexport) LRESULT CALLBACK KBHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if(nCode < 0)
return CallNextHookEx(hHook, nCode, wParam, lParam);

if((wParam == VK_F2) && ((lParam & (1 << 31)) == 0) && g_pfF2Pressed)
{
g_pfF2Pressed();
// Beep(800, 500);

}

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

_declspec(dllexport) void SetF2Callback(LPF2Callback pfCallback)
{
g_pfF2Pressed = pfCallback;
}




// KeyTest.cpp


BOOL LoadHookDLL()
{
...

SetCallback = (LPSetCallback)GetProcAddress(hKBHookDLL, "SetF2Callback");
if(!SetCallback)
return FALSE;

...

return TRUE;
}

void Action()
{
Beep(800, 500);
}

// window WM_CREATE handler

DWORD OnCreate()
{
if(!LoadHookDLL())
return -1;

SetCallback(Action);

return 0;
}





My guess is the problem is to do with the pointer getting passed to the DLL which may be in a different address space (?) and so it is unable to call the function. Seems strange that simply nothing happens though. This is the case though, since if the call to Beep near the top of the above code is uncommented, then I do get a beep, whether my app is active or not.

Anyway, thanks for your help.

Cameron

[edited by - kamrann on June 13, 2002 2:30:22 PM]
sark
sark
Make sure you''ve shared your shared section, by either the linker switch or this:


  

#pragma comment(linker, "/SECTION:SharedBlock,rws")



If you have any more problems show us the code for SetCallback(). Keep the function pointer in the shared section.
IndirectX
IndirectX
Which hook are you setting? Are you setting the hook on your own thread? If yes, then it''s possible that your thread just never get keyboard messages and hence the hook will never be called. If no, is your callback located in the .exe? If yes, then I''m surprised your program hasn''t crashed yet since the callback doesn''t exist in other program''s address space.

In any event, what prevents you from using RegisterHotKey instead of messing with keyboard hooks?
---visit #directxdev on afternet <- not just for directx, despite the name
kamrann
kamrann
OK. Thanks for the suggestions.

sark: the SetCallback code is already posted. From what I understand, data in the shared section has one instance across all attaching processes. So if I want any number of apps to load the DLL and register their own callback function for a keypress, I thought that the callback pointer should NOT be in the shared section?

IndirectX: It''s a system wide WH_KEYBOARD hook, and the callback is a function in an application program which is passed as a function pointer to the DLL. What you''re saying is what I suspected, but as I say it hasn''t crashed. Anyway, there must be some way for an app to pass function pointers to a DLL. How can this be done such that the dll can call the function without address space problems? As for RegisterHotKey, I don''t know how I completely overlooked it. I''ll try it, but I think it won''t work since I really need to synchronize with another program that reacts to a press of F2, and I assume that it probably registered it as a hotkey and so I won''t be able to according to the docs.

Cameron
IndirectX
IndirectX
quote:
Original post by kamrann
I really need to synchronize with another program that reacts to a press of F2, and I assume that it probably registered it as a hotkey and so I won''t be able to according to the docs.


So if I understand you correctly, you need to catch F2 but let another program handle it as well?

I''m not sure if keyboard hook will work. Try WH_GETMESSAGE and see if WM_HOTKEY is posted to the target program, if your keyboard hook isn''t called.

Elaborating on the callback idea, I''d say it won''t work. If your hook is called from another program''s address space, the dll in which the hook resides is loaded into the target process, but your callback which is in exe doesn''t exist in target process! I would advise you to use an interprocess syncronization mechanism such as window messages (either PostMessage or SendMessage, but if you''re using SendMessage don''t get stuck for too long in your message handler), events on which your app waits (possibly a dedicated thread, or periodical checks with timeout of zero), or maybe something else. Only the dll in which the hook resides is present in other programs'' address space, so you won''t be able to *directly* execute the code residing in your exe from that dll.
---visit #directxdev on afternet <- not just for directx, despite the name
kamrann
kamrann
As far as I can tell, the keyboard hook is working fine - it gets called as expected, whether my app is active or not. Its just the callback thats the problem.

As far as this goes, and your other suggestions (I did try using events briefly), I think I need to learn quite a bit more on dlls and IPC. However, I thought since my app (which contains the callback function) called LoadLibrary, it meant the dll was loaded into its address space? But its confusing since the hook procedure is called by the system isn''t it, so what address space would that be in?

Cameron

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.