Plywood: A New Cross-Platform Open Source C++ Framework
preshing.com
preshing.com
I think this works as a good overview.
The above description indicates that it is a very general-purpose framework (handling things as disparate as game engines and web servers) and that it aims to enable code reuse, not just eliminate boilerplate code.
For example think of MFC: you know what that framework is all about (Windows GUI applications), yet the description could easily fit with MFC (and indeed all of the above have been implemented on top of it).
I’ve worked in the game industry for 14 years. Until 2015, I worked as a Technical Architect at Ubisoft Montreal, on franchises such as Rainbow Six, Child of Light and Assassin’s Creed. Before that, I spent a few years developing desktop graphics software at Corel.
https://github.com/arc80/plywood/tree/master/repos/plywood/s...
A video renderer, audio synthesis, parsing, and web server. Linked right from the article. The first is even the first demo in the article.
[0] https://plywood.arc80.com/docs/modules/runtime/api/string/St... [1] https://doc.qt.io/qt-5/qstring.html [2] https://www.qt.io/blog/qt-offering-changes-2020
If so, that turns a PR branch into a single commit onto the target branch (master). Unless the old branches are kept around, the unsquashed commits won’t be available.
If they version it, I could also imagine using master as an orphan branch and just cherry-pick the changes between two tags or commits into it.
¹ https://git-scm.com/docs/git-replace ² https://git.wiki.kernel.org/index.php/GraftPoint
https://git-scm.com/book/en/v2/Git-Tools-Replace gives the exact example of what I had in mind.
Some parts could be replaced by standard C++ library functionality by now. My biggest issue so far: Use of bare pointers, especially in parser code. This should not appear in new code written in 2020. I'm kind of baffled by that as he seems to use stuff like std::move.
This is no replacement for either Unreal or Unity for sure, it's pretty basic in functionality.
They also add a level of indirection, which can manifest as cache misses. If you're iterating through large numbers of objects, memory locality can be a huge gain.
Yeah, the indirection I was referring to generalises to this.
Edit:
You might be saying that STL data structures could have been used by the author to alleviate the memory locality issue, but as noted in another thread, it's common to use custom STL implementations or use entirely custom memory management in performance critical applications, to reduce on memory allocation frequency, memory usage and/or fragmentation. Or maybe the author is just more 133t than thou.
neither shared_ptr nor unique_ptr add any additional indirection compared to raw pointers.
Of course if you can you should use inline value types, but that's a different thing. The parent was talking about replacing raw pointers with smart pointers (personally I have no particular issue with non-owning raw pointers).
I see that he does the same, keeping his own lightweight string class implementation, for instance, and also his own lightweight smart pointer implementations (Owned and Borrowed). I suspect that he also uses bare pointers and new for similar reasons.
It would be interesting to know if he thinks it is necessary, or if he could have used std::string, std::unique_ptr and std::make_unique instead in this framework.
Also as stated its not a game engine so why would it be a replacement for unreal or unity?
I'm curious what this means exactly. Does it mean that requires the non-open source part to function? Or is it a standalone part of the non-open source engine that can be used by other projects (like a library)?
Games often have parts that don't quite belong to the engine layer, but also not strictly to this specific game. It might be small adhoc helper modules, glue code to other 3rd party libraries or similar random stuff.
It looks to be focused on projects that do not use any UI toolkit at all. CLI applications and games, basically.
Opinions?
Otherwise it would be a feature like RTTI that everyone "hates" if enabled by default.
I am hardly a C++ user nowadays, but such stuff interests me, because the Windows Development team managed to push C++/WinRT as replacement for C++/CX, but are declining any improvement to Visual Studio support (at least comparable to C++/CX) until ISO C++ gets similar capabilities to C++/CX.
So given that some C++ usage is required depending on which APIs you want to access from .NET, you can imagine there are many WinDevs not very happy with the downgrade in tooling support.
Back to your point, in what cases might such distinction be relevant?
Here, only one data member is meant to be serialized. The others members are there to accelerate lookups into the first data member. (Full disclosure: that structure isn't actually serialized yet, but the Arc80 Engine which uses Plywood has similar examples.)
Everyone misses compile time reflection because it solves many use cases easily (like serialization) without having to go for a complex solution or incur in performance penalties of runtime reflection. In contrast, I doubt many people care about general runtime reflection which I’d expect to be a mess in C++ and most likely not as fast as people wanted.
Given compile-time reflection, providing standard library functionality for certain runtime reflection tasks (such as providing a list of field information for a struct/class/union, or listing function arguments) could be useful. On the other hand, it could end up being a locale-like scenario where it's either overkill or too weak for your use case, never in the middle.
well put.
However with template metaprogramming and constexpr if there is already quite something when can do into supporting it, today, specially with C++20.
Post C++20, there are ongoing plans to have support for static reflection at compile time, and metaclasses.
Microsoft demoed the current state of their VC++ prototype at Virtual C++2020 days.
"Dynamic Polymorphism with Metaclasses and Code Injection"
If you do not mind relying a bit too hard on the preprocessor you can also do it in plain C [2] (i mean, the C++ approach still relies on it a lot, but the C one goes all the way :-P).
A game engine (for a big published game, not my own stuff) i worked on at the past used this approach (the C++ one) heavily and i think it is also quite common in some frameworks.
Though personally outside of experimentation i just use Free Pascal which provides the functionality as a core feature of the language (and next version will allow attaching arbitrary attributes to properties, which addresses my "i'd like to have a description for this property for the editor without writing a GetPropertyDescription method" wish :-P).
[0] https://pastebin.com/eCYs1tv8
I've read simliar statements before but I don't think I understand how it helps.
struct foo {
int a;
int b;
const char *c;
};
and I want to automatically generate this function: void serialize_foo(foo &obj, ostream &out) {
out.serialize_int(obj.a);
out.serialize_int(obj.b);
out.serialize_string(obj.c);
}
With some sort of reflection, you can automatically build that method with something like this: void emit_serialize_method(class_definition &clazz) {
emit("void serialize_foo(" + clazz.name + "&obj, ostream &out) {");
for (auto &field : clazz.fields) {
emit(" out.serialize_" + field.type + "(obj." + field.name + ");");
}
emit("}");
}
(syntax of course varies).I have to say that framing reflection in terms of deriving an implementation of an interface is pretty powerful. But C++ makes it harder to do this than Rust, because you need to mutate the class definition to insert these methods in C++, but the Rust definition happens outside of the class (as vtable pointers are not contained within the class but passed around separately).
> I have to say that framing reflection in terms of deriving an implementation of an interface is pretty powerful.
Just wait till you see Haskell's Generic. (Not to be confused with generics in other languages.) It turns out for most applications you don't even need to derive an implementation of an interface.
[1] the currently non existing equivalent in C++ has been sometimes refererred as virtual concept. Once upon a time, in the 2.x era, g++ had an extension known as 'signature' which would do exactly that.
[1] http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p059...