I hope this will be a clearer explanation of my point ...
1. I want to create a shared library with the function my_callback. Because I want to support C programs, dlsym, and C++, I want my_callback to be unmangled; therefore, I put it in my_callback.h.That conclusion doesn't follow from the requirements: putting it in my_callback.h is not sufficient. It would only be sufficient if the compiler magically switched language based on file extension, which isn't the case and the expectation of that behaviour is where your problem stems from.
The name is not mangled as a consequence of compiling it as C, not because you put it in a header or because the header has a particular name.
2. I compile my 100%-C library libmc.so.dlsym is always an option, you just have to use the right symbol name. If it's a C++ function then the name will be mangled, which does make it tricker. In your case the symbol name isn't mangled, which admittedly makes things easier :-)
3. program-a needs my_callback without hard-linking. Because my_callback isn't mangled, dlsym is an option.
4. program-b needs my_callback with hard-linking. Because my_callback isn't mangled, program-b must either use extern "C" when including my_callback.h or my_callback.h needs to conditionally use extern "C" if C++ compilation is detected.Right. See below.
This is because gcc infers that my_callback.h is meant to be a C++ header rather than at least implicitly giving it C linkage.See my last diary entry.
The problem isn't apparent until link time, however; gcc mangles the name and an "undefined reference" error occurs.Right. As it should.
The #include <my_callback.h> has exactly the same effect as pasting the contents of that header into the including file at that point. So if the header declares void my_callback(int); it is exactly as if you had written that directly into the including file. Obviously, had you done that, it would declare a function with extern "C++" linkage if you wrote it in a C++ file, and declare a function with extern "C" linkage if you wrote it in a C file. The fact the declaration was instead provided indirectly by including another file is irrelevant, and so is the name of that other file. If you want it to declare a function with extern "C" linkage in all cases then you are responsible for explicitly speciying the language linkage in the C++ case (and the obvious way to do that is with #ifdef __cplusplus etc.)