As someone who has a file with similar hacks, I will say this: I am not a C++ fan, but if you find yourself writing C code where you simulate methods via structs with function pointers often, just use C++ as a basic "C with classes" at that point. You want methods anyway, you have to go through a pointer dereference to call the function, it's just not worth the code weirdness. If you have the grit to use structs with function pointers everywhere, you have the grit to stick to the simpler subset of C++.
I'm torn. The step from C to any c++ is big. Now if you want anybody to be able to use your code they need to be using c++ or you have to provide a C api anyway. On the other hand, manually implementing vtables is annoying. Ive been sticking to pure C and haven't been bothered enough to go back to any c++ yet (about 6 months on my current project). I mostly only miss templated containers so far.
It is more annoying to want to implement an optional function in a class and then have no simple way to check if that optional function is implemented in the object without, having to edit code that guards the call sites every time you add a derived class that implements it, or having to implement your own way of querying the object to know if it is supported.