If I expose a function returning a bool it will return a bool. If I call a function returning a float it will return a float.
I don't have to do any typedefs for the function pointer.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | struct MyDllInterface { virtual bool aFunction() = 0; }; struct MainMenu : MyDllInterface { virtual bool aFunction(); }; struct Gameplay : MyDllInterface { virtual bool aFunction(); }; struct Editor : MyDllInterface { virtual bool aFunction(); }; bool result = engineInterface->aFunction(); |
// the only thing that needs patching on load and reload is the engineInterface pointerNo, there are more pointers to patch - engineInterface pointer, engineInterface vtable and all function pointers in engineInterface vtable. Because after DLL is reloaded the vtable and ints contents can be located in different place. And patching vtable will need to be done in undocumented way, C++ standard doesn't specify how it is implemented.
// the only thing that needs patching on load and reload is the engineInterface pointer
No, there are more pointers to patch - engineInterface pointer, engineInterface vtable and all function pointers in engineInterface vtable. Because after DLL is reloaded the vtable and ints contents can be located in different place. And patching vtable will need to be done in undocumented way, C++ standard doesn't specify how it is implemented.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | SCENE_UPDATE_FUNC(gameplayUpdateAndRender); SCENE_UPDATE_FUNC(editorUpdateAndRender); SCENE_UPDATE_FUNC(mainMenuUpdateAndRender); SCENE_UPDATE_FUNC(settingsUpdateAndRender); enum funcPointerNames{ FUNC_GAMEPLAY_UPDATE, FUNC_EDITOR_UPDATE, FUNC_MAINMENU_UPDATE, FUNC_SETTINGS_UPDATE }; typedef SCENE_UPDATE_FUNC((*gameSceneFunc)); global_var gameSceneFunc g_funcPointers[] = { gameplayUpdateAndRender, editorUpdateAndRender, mainMenuUpdateAndRender, settingsUpdateAndRender }; |
1 | g_funcPointers[GameState->CurrentSceneFunc](MemPool, Platform, Renderer, Input, TimeInfo); |
The dll, on load, makes sure the global function pointers array is initialized every time
And if I ever need to use several types of functions, I can simply store them in an array of void(*)() pointers and cast them to the proper type before invocation.You can avoid casting and maintain type safety like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | typedef void FunctionPtrInt(int); typedef void FunctionPtrFloat(float); struct { FunctionPtrInt* One; FunctionPtrFloat* Two; } static g_funcPointers[] = { { gameplayOne, gameplayTwo }, { editorOne, editorTwo }, { mainMenuOne, mainMenuTwo }, }; g_funcPointers[GameState->CurrentSceneFunc].One(1); g_funcPointers[GameState->CurrentSceneFunc].Two(2.0f); |
jon_valdes
Well, it's just 1 line of code regardless of how many possible scenes you have. A switch statement grows with the number of functions.
Consider:
1 GameState->CurrentSceneFunc(MemPool, Platform, Renderer, Input, TimeInfo);
Versus:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 SCENE_UPDATE_FUNC((*CurrentSceneFunc)); switch(GameState->CurrentScene){ case SceneMenu: CurrentSceneFunc = menuUpdateAndRender; break; case SceneMainGameplay: CurrentSceneFunc = mainGameplayUpdateAndRender; break; case SceneEditor: CurrentSceneFunc = editorUpdateAndRender; break; [...] } CurrentSceneFunc(MemPool, Platform, Renderer, Input, TimeInfo);
It's not a hugely important thing, but it's something I'd like to avoid if possible.
Although from your responses so far I guess there isn't really much one can do in this case..