In other words: "whoosh..."
It's real OOP - just because it doesn't have the syntax doesn't make it faux. You create classes and objects, and reason about them as such.
I don't think OO C is suitable for the "mainstream OOP arena", and I never said it was - you're arguing and disagreeing with a straw man of your own making. For the limited scope of system software, a few regulatory constrained environments, and new hardware, it clearly has its place.
Also, you're not sacrificing all your type safety - yes, with a simple OOP implementation you can cast any object pointer to any other object pointer, which most OO languages would complain about, but it requires a very visible explicit cast to do so. Your objects are still typedef'ed, and can't be used with incompatible methods, or passed as incompatible method parameters without an explicit cast. Your standard method of operation should work in a similar way to an OOP language, except that you need to cast your derived class to its base class when passing it to a method expecting the base class. There are support libraries like GObject that provide an API that will give you static and dynamic type safety.