Handmade Hero»Forums»Code
Jon Valdes
10 posts
Patching function pointers after dll reload?
Hi everyone!

When Casey did the dll autoreload system, he said it could be extended to handle things like fixing function pointers after a dll reload, but he didn't get to say how he'd do it. And well, I kinda need that functionality to do dynamic dispatch in a game I'm working on :(

Off the top of my head I can think of manual ways to do it (like storing an enum instead of the function pointers, then use the enum to switch between the function pointers...) or even piggybacking into the dll main function and manually do the patching from there, but both approaches seem fragile and kinda hackish.

I'd love to make this work in a way that doesn't add much busywork when massaging the game code into shape. Any ideas?

Thanks a bunch in advance!

(Maybe Casey already said something about this on one of the later streams, but I'm now on a 10GB/month plan and I can't afford to watch the videos every day... If that's indeed the case, I'm really sorry for the noise here)
Casey Muratori
801 posts / 1 project
Casey Muratori is a programmer at Molly Rocket on the game 1935 and is the host of the educational programming series Handmade Hero.
Patching function pointers after dll reload?
So, mandatory first question here: what do you mean by "fixing function pointers after a DLL reload"? Like, specifically what kind of code are you writing where you are storing function pointers in the data?

- Casey
Jon Valdes
10 posts
Patching function pointers after dll reload?
Hi Casey,

They're different "update and render" functions for the different "scenes" in the game. Menu, gameplay, scene editor, etc. Using function pointers directly this way is simpler than enums and switches, but it of course breaks down when the dll reloads :(
Casey Muratori
801 posts / 1 project
Casey Muratori is a programmer at Molly Rocket on the game 1935 and is the host of the educational programming series Handmade Hero.
Patching function pointers after dll reload?
OK, so next obligatory question: what makes it "simpler" to use function pointers instead of using a switch statement and a set of enums?

- Casey
Jon Valdes
10 posts
Patching function pointers after dll reload?
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..
Benjamin Kloster
48 posts
Patching function pointers after dll reload?
If code verbosity is what you are worried about, pull the switch statement out into its own function that takes the enum value as argument and returns the appropriate function pointer.

You could also put all those function pointers into an array, with the enum values as indices. Either have the array as a static global variable (I *think* this should work fine with reloading, as long as you don't keep pointers into this array around) or put it into your game memory and reinitialize it after each DLL reload.
Ritchie Brannan
11 posts
Patching function pointers after dll reload?
If you are prepared to use a little C++ this can be a lot simpler.

Create a pure virtual interface with all the functions you want to patch and you will only need to patch a single function which returns this interface.

Obviously you need to have a class in the engine which implements the functions, but this can be a simple bridge to your existing functions.

I do this in my engine, though the interface I return is to an object which can be queried for more interfaces.
Mārtiņš Možeiko
2559 posts / 2 projects
Patching function pointers after dll reload?
Edited by Mārtiņš Možeiko on
How using C++ with virtual interface is simpler than regular C functions?
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
typedef void SceneFun(arg, arg...);

SceneFun* SceneFunctions[] = {
  menuUpdateAndRender,
  mainGameplayUpdateAndRender,
  editorUpdateAndRender,
  ...
};

SceneFunctions[GameState->CurrentScene](a, b, ...);
Ritchie Brannan
11 posts
Patching function pointers after dll reload?
Well for one thing, your functions can all have different parameter lists.

From a code stand point you don't require any special handling for functions with different parameters or even a loop to patch the functions.

To add a new function just add it to the interface and implement it. No tables of data required in either the engine or .dll.

Effectively the virtual function table is implementing all your lookups that you are currently manually patching.
Mārtiņš Možeiko
2559 posts / 2 projects
Patching function pointers after dll reload?
Well for one thing, your functions can all have different parameter lists.
So are functions in OP question.
Ritchie Brannan
11 posts
Patching function pointers after dll reload?
..and your functions can all have different return values. The entire function signature can be different - you can even have overloaded functions with the same name.
Ritchie Brannan
11 posts
Patching function pointers after dll reload?
Basically there is far less code involved if you use a virtual interface.
Mārtiņš Možeiko
2559 posts / 2 projects
Patching function pointers after dll reload?
And how you imagine using such functions with different return types?

1
2
3
Object *blah;

WhatTypeIuseHere? result = blah->CallSceneUpdate(arg1, arg2);
Mārtiņš Možeiko
2559 posts / 2 projects
Patching function pointers after dll reload?
Icabod
Basically there is far less code involved if you use a virtual interface.


I wrote 10 lines to call 3 different functions (counting also empty lines). How many lines of code you'll need to write for C++. Far less than 10? So 3 lines of code?
Ritchie Brannan
11 posts
Patching function pointers after dll reload?
Just call the function directly, so 1 line.