There is one thing that bothers me, C++ function pointers. I’m asking this question because I’m trying to implement callback functions used in my game engine. The issue is, for example:
// Callback function
HRESULT RenderScene(float fps){ HRESULT hr; return S_OK; }
// Set the message
msk->SetMessage(0, SM_RENDERSCENE, (void*) RenderScene);
The problem is COM doesn’t allow function pointers in their member functions. Also, doesn’t allow for polymorphism. As you can see, I made it a void*. Fine with me because I know what the callback function is. The main issue is that I want something that is type-safe.
Now say if the user doesn’t know the callback function declaration. For example,
// Callback function
HRESULT CALLBACK RenderScene() or RenderScene(int fps) or RenderScene(int a, int b)
Is implemented in WndProc as:
...
SM_RENDERSCENE:
((void (_stdcall*)(float fps)) pfn)(1.0f);
break;
...
The first, doesn’t have an argument, therefore, he doesn’t see fps. The second, loses precision. The third, loses precision and has an unused argument. Do you see where I’m going at? Tried using a union but COM doesn’t allow function pointers in the member function.
I tried, and tried again. Nothing works, even the MFC message maps are ugly if they didnt have those macros.
To clarify, I rather have it return an error like E_FAIL or E_INVALIDFUNCTION if the function doesn’t match the specification of SM_RENDERSCENE.
Does anyone have a solution to this problem.
Note: I like the COM specification and I’m not going to change, so focus on the issue not about why I’m using COM. Thank you, any help will do.
No, COM definitely supports function pointers. It is only when you use the subset of COM Automation or need to marshal function calls that you could get in trouble. Which is not the case here, you don’t marshal between processes or threads and don’t need automation since you work with only one language.
The simple problem is that you have the issue that you are trying to protect against, the function pointer definition doesn’t match the implementation. Yes, a (void*) cast will stop the compiler from complaining about it, nothing good happens at runtime.
Your first declaration has the wrong calling convention. Using the STDMETHODIMP macro is wise.
Your second set of declarations have the wrong arguments.
The third snippet is applying an invalid function pointer cast, a cast to a function that returns void instead of HRESULT. And assumes __stdcall even though your RenderScene() function didn’t use STDMETHODIMP or CALLBACK. Which is why you don’t see a proper value for the argument.
Solve function pointer problems by declaring an alias for the pointer type:
And consistenly use RenderSceneCallback in all your declarations. Never cast.