C++调用C库时函数未定义引用的原因及链接问题排查
extern "C"? Let's break down exactly what's happening here—it all boils down to how C and C++ compilers handle function names under the hood.
The Core Issue: Name Mangling
C and C++ compilers treat function names very differently:
- C compilers keep things simple: they use the exact function name as the symbol in the compiled binary. That's why
nm libpkghandler.soshows raw symbols likeprint_tracesandorder_timeout—your C library was compiled with this straightforward naming rule. - C++ compilers do something called name mangling. They encode extra details (like parameter types, return values, and namespaces) into the function's symbol name to support features like function overloading. For example,
print_traces()might get mangled into something like_Z12print_tracesv(the exact format depends on your compiler).
What Went Wrong in Your Experiment
When you moved pkg_handler.h outside the extern "C" block:
- Your C++ compiler (g++) read the function declarations in
pkg_handler.hand assumed they were C++ functions. - It compiled calls to
print_traces()andorder_timeout()to reference their mangled C++ symbol names, not the raw C-style names. - But your
libpkghandler.soonly contains the raw C symbols (since it was compiled with a C compiler). - The linker searched for those mangled symbols, couldn't find them, and threw the "undefined reference" errors you saw.
Think of it like asking for a file named "myfile.txt" when you only have "MYFILE.TXT" in your folder—same core purpose, wrong name, so the system can't match them.
How extern "C" Fixes This
The extern "C" block is C++'s way of saying: "Hey, everything inside here is C code. Don't mangle these function names—treat them like a C compiler would."
When pkg_handler.h was inside the block:
- g++ knew to compile calls to
print_traces()to look for the raw C symbolprint_traces, which matches exactly what's in your .so file. - The linker found the symbols immediately, no errors.
Quick Way to Confirm This
If you want to see the mangled name for yourself:
- Compile your C++ source file (with
pkg_handler.houtsideextern "C") into an object file:g++ -c your_file.cpp -o your_file.o - Run
nm your_file.oand look for references toprint_traces—you'll see a mangled symbol (like_Z12print_tracesv) instead of the raw name. - Compare that to the symbols in
libpkghandler.so—they don't match, hence the error.
The Fix
Just move #include pkg_handler.h back inside the extern "C" block. That tells g++ to handle those function declarations as C code, use the raw symbol names, and the linker will be able to match them up with your pre-compiled C library.
内容的提问来源于stack exchange,提问作者ZR_xdhp

