Cross-platform serialization of plain-old-data doesn't seem too difficult. Naturally, serialization of shared references, forming a distributed graph, is a big challenge to make robust or secure. Similarly, serialization of *functions* - e.g. to represent lazy data (such as infinite streams) - would present significant challenges to make cross-platform or efficient. But if we limit to tree-structured data or complete subgraphs, it is nowhere near "impossible to get right".
There is a common ecosystem option to use schema to build PL-specific types and automatically generate the serializer and parser functions. This isn't specific to protocol buffers; it's also common for DDS, CORBA, and other systems. Some people like this, some people hate it. I tend to prefer writing my own serialization and parser functions, using JSON or MsgPack.