I encountered the following linking issues when trying to use librbd.
The following is my code snippet.
#include <iostream>
#include <rados/librados.hpp>
#include <rbd/librbd.hpp>
int main(){
// Initialize and open an rbd image
std::string pool = "xxx";
std::string image_name = "xxxx";
int r;
librados::Rados cluster;
librados::IoCtx io_ctx;
librbd::Image image;
librbd::RBD rbd;
r = cluster.init("cinder-ctest");
r = cluster.connect();
r = cluster.ioctx_create(pool.c_str(), io_ctx);
r = rbd.open_read_only(io_ctx, image, image_name.c_str(), NULL);
std::string id;
image.get_id(&id); // <- Where the problem occurs
std::cerr << id << std::endl;
return 0;
}
An error occurred when I compiled using the following command
$ g++ main.cc -o info -lrbd -lrados
/tmp/ccOpSFrv.o: In function `main':
main.cc:(.text+0x12b): undefined reference to `librbd::Image::get_id(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*)'
collect2: error: ld returned 1 exit status
but I use nm to see that get_id exists:
$ nm -D /usr/lib64/librbd.so | grep get_id
0000000000083d00 T rbd_get_id
000000000008de10 T _ZN6librbd5Image6get_idEPSs
U _ZN8librados7v14_2_05IoCtx6get_idEv
and it is globally visible:
$ readelf -s /usr/lib64/librbd.so | grep get_id
498: 0000000000083d00 70 FUNC GLOBAL DEFAULT 11 rbd_get_id
559: 000000000008de10 54 FUNC GLOBAL DEFAULT 11 _ZN6librbd5Image6get_idEP
why do I get an error when compiling: undefined reference to librbd::Image::get_id
. It clearly exists, which makes me wonder.
Some background: C++11 changed the std::string
interface slightly by adding noexcept
specifiers to a few member functions, but it turns out that slight change meant that libstdc++ had to re-write their std::string
implementation in a non-ABI-compatible way. For backwards compatibility, they retained the old version and put the new one in an inline namespace so it's named std::__cxx11::basic_string
as far as the linker is concerned. See this page for more info.
That's where you're running into trouble. _ZN6librbd5Image6get_idEPSs
demangles to
librbd::Image::get_id(
std::basic_string<
char,
std::char_traits<char>,
std::allocator<char>
>*
)
That function accepts the old version of std::string
, but you're passing it a pointer to the new version of std::string
. Presumably the version of librbd you have was either built with an old version of GCC, or was purposely built against the old ABI.
You have a few options to work around this:
_GLIBCXX_USE_CXX11_ABI
preprocessor macro to 0
to tell libstdc++ to use the old implementation of std::string
. It doesn't technically fully comply with C++11 and later standard revisions, but it's mostly the same.Seems like you use a C++11-compatible compiler, that generates _ZN6librbd5Image6get_idEPNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
names, but your library was compiled using C++03, C++98 or something like that, before C++11.
If you have access to the library sources, recompile it with C++11, if you don't, compile your program in the C++03 compatibility mode.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.