Your Rust program says it expects a version() function to be defined somewhere and is leaving it up to the loader at runtime (via dlopen()) to find the appropriate symbol from the *.so's dependend on by librustlib.so.
However, version() is defined in your C executable, and it looks like the way it was compiled means the loader will never consider your main executable when looking for the symbol.
Maybe you need to compile the C executable with -rdynamic like in this StackOverflow answer?
Usually for this type of thing you pass a function pointer around. So you pass it to the library, which calls back to the original.
Question: does this work with a dynamically loaded C library? I mean one where you dlopen and dlsym it as well. If it does, then that's one thing. But if it doesn't, then it's not a Rust problem per se (or not only that), it's (also) a linking problem.