"then theoretically any other language could consume that definition"
That was what COM tried to achieve (and before it, DCE RPC, on which a lot of COM is based).
The issue are not languages who have compatible data types - usually compiled languages that use the underlying CPU types, and their in-memory structures are quite "simple", and can be easily addressed using pointers - the issues are often in the interpreted ones (and some vm ones), where data type often have their own representation, and can't be easily passed around.
You can see it easily with "string" types - even compiled languages where the "string" type is native can use different ways to implement it internally - so they are not compatible across calls into different ones (but maybe as read-only buffers).
That's why COM had its own datatypes and all that marshaling stuff to convert them to and from, giving each side of the call something it can use.
Another attempt is doing what XML and JSON do - turn everything into some character-based format, and still needing code to convert to and from (which is usually far less performant than using native types when possible).
Of course, if you can force different languages to abide to a common standard, it's much easier.