Undefined symbol for HDF5 when using g++ - c++

I can't seem to get the c++ bindings for the HDF5 library to compile when using gcc.
The test program is the example found at:
https://support.hdfgroup.org/ftp/HDF5/current/src/unpacked/c++/examples/h5tutr_crtdat.cpp
My cmake file reads as follows:
cmake_minimum_required(VERSION 3.1.0)
project(readhdf5 C CXX)
find_package(HDF5 COMPONENTS C CXX HL REQUIRED)
link_directories(${HDF5_INCLUDE_DIRS})
include_directories(${HDF5_INCLUDE_DIRS})
add_executable(readdata ../src/main.cpp)
target_link_libraries(readdata ${HDF5_LIBRARIES})
target_link_libraries(readdata ${HDF5_CXX_LIBRARIES})
Which I am using with the command:
cmake -DCMAKE_C_COMPILER=gcc-8 -DCMAKE_CXX_COMPILER=g++-8 ..
The error I recieve is:
me#comp:~/Downloads/hdf5-cmake-example-master/build$ make
[ 50%] Linking CXX executable readdata
Undefined symbols for architecture x86_64:
"H5::H5File::H5File(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned int, H5::FileCreatPropList const&, H5::FileAccPropList const&)", referenced from:
_main in main.cpp.o
"H5::H5Location::createDataSet(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, H5::DataType const&, H5::DataSpace const&, H5::DSetCreatPropList const&) const", referenced from:
_main in main.cpp.o
ld: symbol(s) not found for architecture x86_64
collect2: error: ld returned 1 exit status
make[2]: *** [readdata] Error 1
make[1]: *** [CMakeFiles/readdata.dir/all] Error 2
make: *** [all] Error 2
I'm having difficulty working out the cause of the error.
If I do not specify the compiler it defaults to clang/clang++ which compiles fine.
If I use only the C bindings then it compiles fine.
If I specify the compilers as h5cc and h5c++ wrappers, then it compiles fine.
I'm not sure why the gcc/g++ compiler can't find the source code where clang/clang++ can.
I'm using macOS High Sierra.
HDF5 was installed using Homebrew.
Thanks very much for your suggestions.
I understand what an undefined symbol is and how they're usually fixed. However the HDF5 library doesn't seem to follow the typical pattern of how an external library is linked. The question is not about how to fix undefined symbols in general but why they are not found only when using gcc in this case.
I suspect the answer requires specific knowledge of this library rather than general c++.

I encountered very similar problems with HDF5 and C++, which ultimately where related to this ABI issue, which also affects clang (when it cannot be fixed via resorting to an older ABI). If your problem is caused by the same issue, read on.
Ultimately, I solved this by avoiding std::string in the interface to the HDF5 library. This implies
not using any HDF5 functions taking/returning std::string
not using any HDF5 structures using std::string
For most cases you can simply use the version of the HDF5 routines taking const char* and pass string::c_str(). However, there are two more difficult cases.
HDF5 exceptions are based on std::string, so you cannot use them, i.e. catch other than via catch(...)
Reading a std::string via HDF5. To this end I actually re-implemented the corresponding routine (stolen from the HDF5 source code) to compile it with the correct ABI for std::string. Here it is:
//
// reading a std::string, see H5DataSet.cpp
//
std::string read_string(H5::DataSet const&data_set,
H5::DataType const&mem_type,
H5::DataSpace const&mem_space,
H5::DataSpace const&file_space,
H5::DSetMemXferPropList const&xfer_plist
= H5::DSetMemXferPropList::DEFAULT)
{
const auto is_variable_len = H5Tis_variable_str(mem_type.getId());
if(is_variable_len<0)
throw std::runtime_error("read_string: H5Tis_variable_str failed");
std::string strg;
if(!is_variable_len) {
const auto data_size = data_set.getInMemDataSize();
if(data_size>0) {
std::unique_ptr<char[]> strg_C{new char[data_size+1]};
std::memset(strg_C.get(), 0, data_size+1);
if(0>H5Dread(data_set.getId(), mem_type.getId(), mem_space.getId(),
file_space.getId(), xfer_plist.getId(), strg_C.get()))
throw std::runtime_error("read_string: H5Dread failed for fixed length string");
strg = strg_C.get();
}
} else {
char*strg_C;
if(0>H5Dread(data_set.getId(), mem_type.getId(), mem_space.getId(),
file_space.getId(), xfer_plist.getId(), &strg_C))
throw std::runtime_error("read_string: H5Dread failed for variable length string");
strg = strg_C;
std::free(strg_C);
}
return strg;
}

Related

Undefined symbols error on c++/qt6 app when linking on macos

I use g++-12 and qt6 installed via homebrew.
At linking my executable on macos, I get this error:
Undefined symbols for architecture x86_64:
"__ZN9QMetaType25registerConverterFunctionERKSt8functionIFbPKvPvEES_S_", referenced from:
The function it's not finding is:
QMetaType::registerConverterFunction(std::function<bool (void const*, void*)> const&, QMetaType, QMetaType)
but in the QtCore lib, the closest corresponding function I can find is:
QMetaType::registerConverterFunction(std::__1::function<bool (void const*, void*)> const&, QMetaType, QMetaType)
Notice the ::__1 namespace
I never got into this kind of problem. Any clue where this comes from?
(the codes compile fine on linux and I can even cross compile it on linux for windows via mingw)

Open CV: cv::LineIterator undefined when compiling for Mac M1

I have an error of Undefined symbol cv::LineIterator::LineIterator(cv::Mat const&, cv::Point_<int>, cv::Point_<int>, int, bool). So I've stumbled upon this issue that I am not sure if it is a bug but I cannot figure out how to fix it or what I am doing wrong.
I am trying to compile a library that uses OpenCV 4.5.1 that I compiled myself for a Mac Catalyst architecture. The OpenCV library I compiled for both arm64 and x86_64 architectures
$ lipo -info opencv2macos.framework/opencv2macos
Architectures in the fat file: opencv2macos.framework/opencv2macos are: x86_64 arm64
However when I try to compile a library that instantiates a cv::LineIterator line_it(mask, cv::Point(2, 4), cv::Point(10, 20), 8, false) I get this error:
Undefined symbols for architecture arm64:
"cv::LineIterator::LineIterator(cv::Mat const&, cv::Point_<int>, cv::Point_<int>, int, bool)", referenced from:
getPointCorresp(Eigen::Matrix<double, 3, 1, 0, 3, 1> const&, Eigen::Matrix<double, 3, 1, 0, 3, 1> const&, cv::Mat const&, std::__1::vector<cv::Point_<float>, std::__1::allocator<cv::Point_<float> > > const&, cv::Mat const&, bool) in CMAUtil.o
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Any idea what could be going wrong here?
After more researching and investigating, the issue was because I was using 2 opencv2 frameworks, one compiled for iOS devices and one compiled for Mac Catalyst.
When I compiled the framework for Catalyst I used a flag to change the name of the framework from opencv2 to opencv2macos which meant that the include headers were supposed to be like #include<opencv2macos/core.hpp>. However when I looked into a few more headers I could find #include<opencv2/imgproc.hpp> which explains why my project was somehow linking to the wrong framework - it was linking to code from opencv2.framework instead of opencv2macos.framework and because the two were different versions (the first one was 4.1.1 and the second was 4.5.1) I guess there was discrepancy within the implementation.

Luabind Undefined Symbols/ Luabind::scope::scope

I have just started working with Luabind, and have attempted to run the Hello World test specified at http://www.rasterbar.com/products/luabind/docs.html#calling-lua-functions. However, this provides an undefined symbol error when attempted to compile.
Undefined symbols for architecture x86_64:
"luabind::scope::scope(std::__1::auto_ptr<luabind::detail::registration>)", referenced from:
luabind::scope luabind::def<void (*)(), luabind::detail::null_type>(char const*, void (*)(), luabind::detail::null_type const&) in TestClass.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Other functions such as luabind::open and luabind::call_function work correctly.
I installed both luabind and lua 5.1 through homebrew on osx.
It looks to me like you are compiling your program against libc++ and trying to link to a luabind library that was compiled against the stdlibc++ library.
The clue is std::__1::auto_ptr. This __1 inline namespace is used by libc++ to differentiate it's ABI from stdlibc++
Thus if
luabind::scope::scope(std::__1::auto_ptr<luabind::detail::registration>)
Cannot be found it is likely because libluabind doesn't have it. Dumping it's exported symbols you might find it has
luabind::scope::scope(std::auto_ptr<luabind::detail::registration>)
Instead.
If I am right, simply recompile libluabind targeting libc++ and you should find it works with your test program.

Trying to compile C++ code on mac

I'm trying to compile some C++ code on my mac. I can run it using Xcode, but when I try to compile from the terminal using gcc I get the following error:
Undefined symbols for architecture x86_64:
"std::cout", referenced from:
_main in ccOJDOlb.o
"std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)", referenced from:
_main in ccOJDOlb.o
"std::ios_base::Init::Init()", referenced from:
__static_initialization_and_destruction_0(int, int)in ccOJDOlb.o
"std::ios_base::Init::~Init()", referenced from:
___tcf_0 in ccOJDOlb.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status
Anyone know what might be going on?
ld: symbol(s) not found for architecture x86_64
This is saying that 'ld', the linker, is not able to find definitions for some symbols your program uses. So you know compilation has succeeded.
And ld lists the specific symbols. Notice that they are all from the standard library. This should tell you that the standard library is probably not being found by the linker.
Typically when you use a library you have to tell the compiler toolchain using a link flag. But for a language's standard library the compilers in the GNU compiler collection generally just assume you want the library for that language. So running the gcc command automatically includes the C standard libraries, running g++ automatically includes the C++ standard libraries, etc. But notice, running 'gcc' does not automatically link in the C++ standard library. It's very likely that you're running the command 'gcc' and simply not adding the correct linker flag for the C++ standard library.
If for some reason you want to use gcc and not g++ you'll have to explicitly state that you want the standard library, using a flag like -lstdc++.
Also, unless you really want gcc and you're installing the latest versions of it yourself on OS X you may want to switch over to clang/clang++ and the libc++ implementation of the C++ standard library. The gcc that comes with Xcode is based on an old version, and the standard library is similarly old. Xcode has been transitioning to clang as the system compiler for some time now. The clang compiler driver has basic compatibility with gcc so you use many of the same basic flags. Here's a good set to start with:
clang++ -std=c++11 -stdlib=libc++ -Wall -Wextra
I try to compile from the terminal using gcc
Then try g++ instead of plain ol' gcc. The former automatically links against the C++ standard library, the latter does not.

Undefinded symbols when linking OpenCV

I'm trying to link static libraries for the OpenCV library into my project, yet I get the error:
Undefined symbols for architecture armv7:
"__ZN2cv9ExceptionC1EiRKSsS2_S2_i", referenced from:
__ZL16icvGenerateQuadsPP8CvCBQuadPP10CvCBCornerP12CvMemStorageP5CvMati in libopencv_calib3d.a(calibinit.o)
_cvFindChessboardCorners in libopencv_calib3d.a(calibinit.o)
ld: symbol(s) not found for architecture armv7
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I have no ideas what that symbol "ZN2cv9ExceptionC1EiRKSsS2_S2_i" should be, that string of Letters found in any source or header file I used to build the static libraries.
Could anyone who's more experienced with the linker explain these errors to me?
EDIT: 01.07. haven't solved this yet, just opted out of checkerboard-detection with calib3d and went for a less complicated circle detection using features2D that gives no linking error.
Most probably you put OpenCV libs in wrong order. Try the following order in your link list:
opencv_contrib opencv_legacy opencv_videostab opencv_photo opencv_stitching opencv_objdetect opencv_video opencv_ml opencv_calib3d opencv_features2d opencv_highgui opencv_flann opencv_imgproc opencv_core
You can use c++filt to unmangle the undefined symbol to find the actual function name.
$ c++filt.exe __ZN2cv9ExceptionC1EiRKSsS2_S2_i
cv::Exception::Exception(int, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int)
Then you'll have to identify which source file contains this function and link in the library corresponding to that.