pothosware / SoapySDR

Vendor and platform neutral SDR support library.

Home Page:https://github.com/pothosware/SoapySDR/wiki

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Build fails: undefined symbol: SoapySDR::KwargsToString

yurivict opened this issue · comments

ld: error: undefined symbol: SoapySDR::KwargsToString(std::__1::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>> const, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>>> const&)

I think that there is another bug: why is SoapySDR even involved when the option SOAPYSDR is set to false by default?

Version: 1.0.0-alpha1
SoapySDR-0.8.1
clang-16
FreeBSD 14.0

This seems to be a ABI linking error.

By default SoapySDR seems to do C++ linkage which is OK when you build both your application and Soapy with the same compiler and [std]libc++. As soon as these do not match (e.g. app with stdlibc++ and soapy with libc++, or different compiler versions) then there is an ABI mismatch.

I tried to work around this using soapy's C-API which helps because of the C-Linkage (which has more ABI guarantees):

See for example here. PRO: linkage isn't a problem anymore. CON: you have C-style resource management where there might be memory leaks and ASAN issues (N.B. we are investigating the latter).

Thanks!
Closing as it's not likely that we can work around (or even warn on) C++ ABI mismatch. But do comment and update if there is anything to improve here.

In the link I provided, there is a C++ wrapper around the C-API that makes builds between different compilers and [std]libc++ compatible. The path through the extern "C" linkage works.

Maybe this could be integrated into SoapySDR?

Similarly, to detect these types and other CI-related issue, it might be worthwhile to incorporate something similar to this:
https://github.com/JuliaTelecom/SoapyLoopback
in the SoapySDR core. That would help debugging, unit tests, and fixing ASAN, UBSAN, and TSAN issues much easier IMO.

Maybe @guruofquality, @cjcliffe, and/or others who seemed to have worked a lot on this may help?

Avoiding the C++ ABI will of course help. We can't provide a compiled C++ wrapper since part of that solution is to build that wrapper with the ABI expectations of your projects.

On the other hand I had good success with these bugs in the past by methodically tracking down and avoiding risky API (on parts like polymorphism and implicit bahaviour).
But "dumbing down" the C++ API will likely be breaking.

Btw, the original error shows a safety feature in action: libc++ uses inline namespaces to help ensure that ABI incompatible types cannot be mistaken for one another; if an interface uses libc++ std::string directly a library expecting libstdc++ std::string will not link to the interface, because the actual symbols are different: std::string vs. std::__1::string.
The only way out of that incompatibility would be to forgo std::string -- not really an option for the C++ API.

@zuckschwerdt my proposal is not to forgo the C++ API but rather use an immediate C++ -> C-API (ABI backward/forward compatibility) -> C++ API between the user's application and soapy abstraction.

This is also used in other C++-based libraries, for example, libzmq to allow for non-C++ API bindings (Python, etc.).

but rather use an immediate C++ -> C-API (ABI backward/forward compatibility) -> C++ API

Understood. But that would have to be source and can't be provided with the Soapy lib (except maybe as a header-only thing).