Pointer to a function

Dear,

I had done an event handler which is simply a structure that has 2 members:
1- message code (i.e. mCode)
2- pointer to the function to be executed (i.e. functionPtr)

The code is as below:

1
2
3
4
typedef struct BsolEvent {
	UINT		mCode;
	long		(*functionPtr)(BsolEventArgs);
};

I have a BsolEvent array in which I need to set specific messages codes and its corresponding function. My problem is that I'm not able to assign the function to the functionPtr knowing that the functions I'm assigning are already defined in the header file. The code is as below:

1
2
3
4
BsolEvent eHandler [100];

eHandler[0].mCode = WM_CREATE; 
eHandler[0].functionPtr = &BsolForm::BsolOnCreate; 

Upon compilation, I'm getting the below error:

1
2
3
error C2440: '=' : 
cannot convert from 'long (__thiscall BsolForm::* )(BsolEventHandler::BsolEventArgs)' 
to 'long (__cdecl *)(BsolEventHandler::BsolEventArgs)'


Please any suggestions or is there anything missing?

Regards,
Ahmad
Did you get that from me? That looks like my setup exactly. I got it from Douglas Boling and his book "Programming Windows CE". He claims he got it from Ray Duncan. In any case, wherever it came from, I have a whole tutorial on its inner logic, theory, and construction here...

http://www.jose.it-berater.org/smfforum/index.php?topic=3391.0

Here's a simple template demo for a Hello, World without the hello....

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
//Main.h
#ifndef Main_h
#define Main_h

#define dim(x) (sizeof(x) / sizeof(x[0]))

typedef struct WindowsEventArguments
{
 HWND                         hWnd;
 WPARAM                       wParam;
 LPARAM                       lParam;
 HINSTANCE                    hIns;
}WndEventArgs, *lpWndEventArgs;

long fnWndProc_OnCreate       (lpWndEventArgs Wea);
long fnWndProc_OnDestroy      (lpWndEventArgs Wea);

struct EVENTHANDLER
{
 unsigned int                 iMsg;
 long                         (*fnPtr)(lpWndEventArgs);
};

const EVENTHANDLER EventHandler[]=
{
 {WM_CREATE,                  fnWndProc_OnCreate},
 {WM_DESTROY,                 fnWndProc_OnDestroy}
};
#endif 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
//Main.cpp
#include <windows.h>
#include <tchar.h>
#include "Main.h"


long fnWndProc_OnCreate(lpWndEventArgs Wea)
{
 Wea->hIns=((LPCREATESTRUCT)Wea->lParam)->hInstance;
 return 0;
}


long fnWndProc_OnDestroy(lpWndEventArgs Wea)
{
 PostQuitMessage(0);
 return 0;
}



LRESULT CALLBACK fnWndProc(HWND hwnd, unsigned int msg, WPARAM wParam, LPARAM lParam)
{
 WndEventArgs Wea;

 for(unsigned int i=0; i<dim(EventHandler); i++)
 {
     if(EventHandler[i].iMsg==msg)
     {
        Wea.hWnd=hwnd, Wea.lParam=lParam, Wea.wParam=wParam;
        return (*EventHandler[i].fnPtr)(&Wea);
     }
 }

 return (DefWindowProc(hwnd, msg, wParam, lParam));
}


int WINAPI WinMain(HINSTANCE hIns, HINSTANCE hPrevIns, LPSTR lpszArgument, int iShow)
{
 TCHAR szClassName[]=_T("Function Pointer Demo");
 WNDCLASSEX wc;
 MSG messages;
 HWND hWnd;

 wc.lpszClassName=szClassName;                wc.lpfnWndProc=fnWndProc;
 wc.cbSize=sizeof (WNDCLASSEX);               wc.style=CS_DBLCLKS;
 wc.hIcon=LoadIcon(NULL,IDI_APPLICATION);     wc.hInstance=hIns;
 wc.hIconSm=LoadIcon(NULL, IDI_APPLICATION);  wc.hCursor=LoadCursor(NULL,IDC_ARROW);
 wc.hbrBackground=(HBRUSH)COLOR_BTNSHADOW;    wc.cbWndExtra=0;
 wc.lpszMenuName=NULL;                        wc.cbClsExtra=0;
 RegisterClassEx(&wc);
 hWnd=CreateWindowEx(0,szClassName,szClassName,WS_OVERLAPPEDWINDOW,75,75,320,305,HWND_DESKTOP,0,hIns,0);
 ShowWindow(hWnd,iShow);
 while(GetMessage(&messages,NULL,0,0))
 {
    TranslateMessage(&messages);
    DispatchMessage(&messages);
 }

 return messages.wParam;
}


This is my standard way of coding both C++ and PowerBASIC apps for both Windows and Windows CE. Has been for years.
Last edited on
Once you do this and understand it, you'll never go back to the standard switch construction. Its too unwieldly. I write apps with tens of thousands of lines of code, and this setup forms the basis of an organization principal, so to speak. I'm kind of amazed anyone asked about it. I don't see it much widely used, excapt possibly by advanced coders.
heeeeyyyyy... this code of editbox is your code ?? Then I would say it is really amazing and interesting freddie.. I got the idea from your code and using your implementation with slight modifications.

In your code, the definition of the function pointer and the assignment are both in the same class. Where as for my code, the function pointer is a member in a class named BsolEventHandler and the BsolEvent array, to which the assignment is done, belongs to another class named BsolForm.
I am reading about the issue and it seems that I have to use class name and scope operator in the function pointer definition but I couldn't reach the suitable way.

Can you help in that man specially I'm using your implementation ;)

Ahmad
This error

error C2440: '=' : 
cannot convert from 'long (__thiscall BsolForm::* )(BsolEventHandler::BsolEventArgs)' 
to 'long (__cdecl *)(BsolEventHandler::BsolEventArgs)'

is because you're trying to use a member function with a normal function pointer.

This declaration long (*functionPtr)(BsolEventArgs); is a pointer to a regular (global) or a static class member. That is, a function that can be called without reference to an instance.

The "__thiscall" is pointing to the fact that your BsolOnCreate() method (of class BsolForm) needs to be called on an instance, eg form1.BsolOnCreate(); or pform->BsolOnCreate();

If you need to call a member function, you need to use a member function pointer.

Andy
Last edited on
I won't have a chance to look at this until Monday or Tuesday Ahmad. But first chance I get, I'll see about implementing that function pointer thing you like with classes. Then I'll reply to this post with an example.
Thanks Andy for your helpful post.

I had fixed the compilation error by defining all the needed functions as global functions and not as member functions of BsolForm class. So that the function pointer and the functions to assigned are all compatible. However, the application is crashing upon allocating memory objects by calling the new operator. It is giving:

Unhandled exception at 0x758ad36f in BSolutionsApps.exe: Microsoft C++ exception: std::bad_alloc at memory location 0x003cf71c..

The last object that is allocated is the BsolEventHandler and it is crashing directly on the next constructor call of another object.

The BsolEventHandler class is:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class BsolEventHandler {
	public:
		typedef struct BsolEventArgs {
			HWND		ehWnd;
			UINT		eMsg;
			WPARAM		ewParam;
			LPARAM		elParam;
			HINSTANCE	ehIns;
		};

		typedef struct BsolEvent {
			UINT		mCode;
			long		(*functionPtr)(BsolEventArgs *);
		};

		BsolEvent eHandler[1];

		DLL_BSOLEVENTMANAGER BsolEventHandler();
};


Please let me know if the class is causing the Unhandled exception.

Regards,
You class looks pretty benign to me, apart from the DLL_BSOLEVENTMANAGER. Is that a macro of some kind?

Have you told Visual Studio to break when the exception is thrown, so you can see what was going on?
Last edited on
Andy, the problem is solved. It was a silly mistake that was resetting the already allocated addresses (memory) to null.
Regarding the DLL_BSOLEVENTMANAGER, it is a macro defined for the dll export / import as below:
1
2
3
4
5
#ifdef BSOLEVENTMANAGER_EXPORTS
	#define DLL_BSOLEVENTMANAGER __declspec(dllexport)
#else
	#define DLL_BSOLEVENTMANAGER __declspec(dllimport)
#endif 

Anyway thanks every body and happy new year to all
Regards,
Ahmad
I asked about DLL_BSOLEVENTMANAGER as I've never seen it applied to a class method (at least, a non-static one). Usually to the whole class.
Topic archived. No new replies allowed.