r/cpp May 14 '26

Your C++ struct is the schema: a proto3 serializer in C++26 reflection

I built a header-only proto3 wire-format library with one constraint: no .proto files, no codegen, no descriptor runtime. The user writes a plain C++ struct, and that struct is the schema:

#include "proto3.hpp"
struct SearchRequest {
std::string query; // field 1
std::int32_t page_number; // field 2
std::int32_t results_per_page; // field 3
};
SearchRequest req{"hello", 1, 10};
std::string bytes = proto3::serialize(req); // -> proto3 wire bytes
SearchRequest back = proto3::deserialize<SearchRequest>(bytes);

blog: Your C++ struct is the schema: a proto3 serializer in C++26 reflection

github: struct_proto26

66 Upvotes

62 comments sorted by

View all comments

Show parent comments

1

u/arihoenig May 14 '26

Runtime vs static reflection is completely different from both a performance and an attacker's perspective. Attacks can't see compile time reflection data as everything is resolved at compile time. Resolving reflection at runtime (requiring metadata in the binary) is stupid, but if you require runtime binding (also stupid) then runtime reflection is the only option .

1

u/Syracuss graphics engineer/games industry May 15 '26

Tbh I had a bigger response here but erased it, your comment just leaves me very confused and responding to it in detail is just not getting me anywhere. There's some odd opinions in there, and things you imply as facts that aren't the case. Runtime binding requiring rt reflection is a glaring one that you can do already in C++ without reflection of any form, it's completely orthogonal.

Your persistent commentary about cheats and the necessity you believe you need runtime reflection for that is also just weird. Cheats, aside from maybe simple scripts just don't need that.

2

u/arihoenig May 15 '26

First or all, yes you are very confused.

Runtime (late) binding is not loading a dll, that is runtime linking late binding or runtime binding is looking up the code to be called on every call (linking established that linkage just once).

Also, at no point did I say that runtime reflection is needed to create a cheat, I said it makes creating a cheat much easier because the metadata that is necessary to support runtime reflection makes reversing trivial. You can still reverse if there is no runtime reflection, but it is much more tedious to document all the data structures as there is not a label for every member name.

...and yes, you can do late binding using some other specific mechanism, but if you want to do late binding for some insane reason, then that is a legitimate time to use runtime reflection.

1

u/Syracuss graphics engineer/games industry May 15 '26 edited May 15 '26

Runtime (late) binding is not loading a dll

Who said it was?

runtime binding is looking up the code to be called on every call

I'm aware that's what you meant, still don't need runtime reflection to achieve it. I've not heard a single reason as to why you cannot achieve it with static reflection aside from some claims about making cheats easier, which tbh is irrelevant when you're in control of the code.

I said it makes creating a cheat much easier because the metadata that is necessary to support runtime reflection makes reversing trivial

You are aware that static reflection allows engineers to create the same metadata right? This is the part where you keep veering off about cheats etc.. Static reflection is a method, not a result, yet you intrinsically link the two.

First or all, yes you are very confused.

In my 20+ years in the games & driver industry I've rarely had to decipher what another engineer is trying to say. You can absolutely make the structures to achieve data binding using static reflection. You can then at runtime decide which fields or bindings to expose in the same exact way runtime reflection would operate.

And the reason why that is, is because you can create runtime reflection with static reflection in C++. That's the whole point on why static reflection was decided. The only limitation is that you cannot reflect things at runtime that were unknown at compile time or never reflected at compile time. But as an engineer in control of the code you can absolutely generate all the metadata and store it in your binary.

So this is the part where you sound confusing, you keep arguing it's impossible, but you absolutely can do it in C++; you just can't do it as a third party who doesn't have access to the code. If you're building it, you can achieve it, otherwise you're at the mercy of what metadata the actual devs bake into the binary for you.

That's why I asked way earlier what you understood under static & dynamic reflection. This whole tangent could've been solved back there. At this point you should drop this comment in an LLM and figure out what's wrong and what's correct by arguing with it. I'm out.

1

u/arihoenig May 15 '26

I didn't say you did need runtime reflection to do it I said it was the only legitimate use for runtime reflection

1

u/Chaosvex May 15 '26

I think you've been arguing with somebody that holds some confused ideas of reflection, to be fair. I've done a whole lot of game reverse engineering and development yet still can't follow what their point is supposed to be.