qt dll compatibility between compilers - c++

Qt library states binary compatibility across major releases. But what about compatibility between different compilers?
For example, I have an application and 2 dlls that use Qt (dynamically linked). But one of them is built with MSVC and the other with MinGW. Thus they are linked to different builds of Qt library (of the same version).
The question is: is it possible for these dlls to work together using one shared Qt dll?
If not then what workarounds are possible considering that changing the compiler is not an option?
I looked at Qt dlls with dependency walker and I see that there are dozens of exported functions which have compiler-scpecific name mangling. So it seems that it is not possible to make them work together.

C++ does not have standard ABI. That means, binaries including DLL files aren't usually compatible between compilers (they may not even be compatible between different build options on same compiler...). This is is the case with MSVC vs. MinGW, no DLL compatibility.
Plain C libraries have a defined ABI on Windows, so they may be used with any compiler (you may still run into problems with libraries having incompatible dependencies, even if ABI is compatible).
If recompiling one library is not an option, then the only workaround I know is to have separate processes, which then communicate using some IPC mechanism. If both libraries offer GUI elements, and you want to mix them in same GUI, that's not possible (or at least it is hard, you need to open window of other app in the window of another, sort of like an overlay).

Related

Distributed dll and c++ objects - how some libraries handle this?

Recently I found that passing/exposing objects to/from dll is dangerous if executable and dll was compiled with different compilers or even with different version of the same compiler or even with different settings of the same compiler! To say I was surprised is to say nothing - all this time I thought I can create a dynamic library and safely distribute it.
Now having this knowledge I wonder how certain libraries work? Let's take a dll in system32 folder. With dependency Walker I can see that in, say, d3d11.dll functions exposed with C parameter - I guess this is C convention which gives us a guarantee it will work. Also I know that d3d11 works with COM objects, so there's no risk of creating an object in dll and destroying it in exe.
But now let's take any Qt dll - the functions exported as c++ and have all their names mangled. I remember when I installed the framework I specified my compiler - MSVC2013, but I didn't specified a version! I can use a dll compiled with update1 compiler in update5 compiler and I can't remember any strange behavior. How it works then? How they handled mangled function name resolve, parameters passing?
The usual reason that a library under windows has to be compiled with the same compiler is that the C++ standard library is not ABI compatible between different version of MSVC++. If a library uses the C++ Standard library across the dll boundary this is ok as long as the C++ standard library is identical in the library and the compiler that uses the library.
Qt expose there own strings (QString) and vectors(QVector) etc, instead of std::string and std::vector, therefore Qt doesn't expose the C++ standard library through the dll boundary, hence the Qt dll works with all versions of Visual Studio.

Are C and C++ .lib files portable?

Assuming the code compiled is actually portable (just using standard library stuff or whatever), could I use the same .lib for my projects across multiple platforms, or can they only run on the platform they were compiled on?
I'm porting my C++ project from Windows to Linux and I use a few 3rd party libraries including openAL, FreeType and FreeImage, and I would like to know if I have to get/recompile new library files.
The dynamic linkers on Windows and Linux work in completely different ways. On Linux the linker will expect elf format .so files. Windows however uses .lib and .dll files which are in a different, incompatible format.
Even if you were to find a way around this, the default calling conventions between the two OSes are different. C function calls place the arguments into different registers so it would be impossible to call functions in these lib files without having the compiler use a custom calling convention, however this would prevent any other code from calling your libraries.
The Wine Project has created a compatibility layer to allow Windows binaries to call into libraries compiled for Linux, however there is a significant performance and complexity penalty to such a layer.
In short, you would be best off in nearly every case to recompile the project for both OSes separately. The libraries you mention (afaik) are all available for Linux also so porting should be a breeze.
The entire purpose of languages like C++ is to provide a platform-agnostic source code abstraction that is portable, because the code created by compiling your C++ is not.
You shall have to rebuild it for your target platform.
.lib files contain platform-specific object code. You will need different ones for each platform.
You will have to recompile the other libraries on each platform you port to.

Name mangling in existing libs - conflict

We have a lot of compiled C++ tools including some statically linked C++ libraries. We had extended some libs and of course recompiled it -> now the newer dll's are not compatible with the older C++ tools!
error:
TransceiveDataRaw#CCommonUtils#RegTestAPI##QAEIPAEH0AAHPBD2#Z could
not be located in the dynamic link library IFX_CC_RegTestBase.dll
Is there any way to ignore this name mangling without recompiling our tools (there are hundreds of them)?
Probably not. Different C++ compilers (and sometimes different versions of the same compiler) use different name mangling schemes, and in a way this is a safety mechanism. Along with a name mangling system, there are runtime mechanisms unique to a given compiler, and these won't be compatible either: virtual method dispatch, for example. The fact that these won't link is probably saving you from building an executable that would just crash and burn.

C++ Dynamic Library Compiling/Linking

I know that if I link my c++ program to a dynamic library (DLL) that was built with a different version of Visual Studio, it won't work because of the binary compatibility issue.
(I have experienced this with Boost library and VS 2005 and 2008)
But my question is: is this true for all versions of MSVS? Does this apply to static libraries(LIB) as well? Is this an issue with GCC & Linux as well? and finally how about linking in VS to a DLL built with MinGW?
By the way aside from cross-platform or cross-compiler, why can't two version of the same compiler(VS) be compatibile?
Hi. I know that if I link my c++ program to a dynamic library (DLL) that was built with a different version of Visual Studio, it won't work because of the binary compatibility issue. (I have experienced this with Boost library and VS 2005 and 2008)
I do not remember ever seeing MS changing the ABI, so technically different versions of the compiler will produce the same output (given the same flags (see below)).
Therefore I don't think this is not incompatibilities in Dev Studio but changes in Boost.
Different versions of boost are not backwards compatible (in binary, source they are backward compatible).
But my question is: is this true for all versions of MSVS?
I don't believe there is a problem. Now if you use different flags you can make the object files incompatible. This is why debug/release binaries are built into separate directories and linked against different versions of the standard run-time.
Does this apply to static libraries(LIB) as well?
You must link against the correct static library. But once the static library is in your code it is stuck there all resolved names will not be re-resolved at a later date.
Is this an issue with GCC & Linux as well?
Yes. GCC has broken backwards compatability in the ABI a couple of times (several on purpose (some by mistake)). This is not a real issue as on Linux code is usually distributed as source and you compile it on your platform and it will work.
and finally how about linking in VS to a DLL built with MinGW?
Sorry I don't know.
By the way aside from cross-platform or cross-compiler, why can't two version of the same compiler(VS) be compatibile?
Well fully optimized code objects may be compressed more thus alignment is different. Other compiler flags may affect the way code is generated that is incompatible with other binary objects (changing the way functions are called (all parameters on the stack or some parameters in registers)). Technically only objects compiled with exactly the same flags should be linked together (technically it is a bit looser than that as a lot of flags don't affect the binary compatibility).
Note some libraries are released with multiple versions of the same library that are compiled in different ways. You usually distinguish the library by the extension on the end. At my last job we used the following convention.
libASR.dll // A Sincgle threaded Relase version lib
libASD.dll // A Single threaded Debug version
libAMR.dll // A Multi threaded Release version
libAMD.dll // A Multi threaded Debug version
If properly built, DLLs should be programming-language and version neutral. You can link to DLLs built with VB, C, C++, etc.
You can use dependency walker to examine the exported functions in the dll.
To answer part of your question, GCC/Linux does not have this problem. At least, not as often. libstdc++ and glibc are the standard C++/C libraries on GNU systems, and the authors of those libraries go to efforts to avoid breaking compatibility. glibc is pretty much always backward compatible, but libstdc++ has broken ABI several times in the past and probably will again in the future.
It is very difficult to write stable ABIs in C++ compared to C, because the automatic features in C++ take away some of the control you need to maintain an ABI. Especially once you get into templates and inline functions, where some of the code gets embedded in your application rather than staying contained in the shared library. That means that the object's structure can't ever change without requiring a recompilation of the application.
In practice, it isn't a huge deal on Windows. It would be fantastic if Microsoft just made the MSI installer know how to grab Microsoft-provided DLLs from Windows Update when an app is installed that needs them, but simply adding the redistributable to an InnoSetup-generated installer works well enough.

Are C++ libs created with different versions of Visual Studio compatible with each other?

I am creating a open-source C++ library using Visual Studio 2005. I would like to provide prebuilt libs along with the source code. Are these libs, built with VS2005, also going to work with newer versions of Visual Studio (esp VS Express Edition 2008)? Or do I need to provide separate libs per VS version?
Not normally, no. Libraries built with the VS tools are linked into the 'Microsoft C Runtime' (called MSVCRT followed by a version number) which provides C and C++ standard library functions, and if you attempt to run a program that requires two different versions of this runtime then errors will occur.
On top of this, different compiler versions churn out different compiled code and the code from one compiler version frequently isn't compatible with another apart from in the most trivial cases (and if they churned out the same code then there would be no point having different versions :))
If you are distributing static libraries, you may be able to distribute version-independent libraries, depending on exactly what you are doing. If you are only making calls to the OS, then you may be OK. C RTL functions, maybe. But if you use any C++ Standard Library functions, classes, or templates, then probably not.
If distributing DLLs, you will need separate libraries for each VS version. Sometimes you even need separate libraries for various service-pack levels. And as mentioned by VolkerK, users of your library will have to use compatible compiler and linker settings. And even if you do everything right, users may need to link with other libraries that are somehow incompatible with yours.
Due to these issues, instead of spending time trying to build all these libraries for your users, I'd spend the time making them as easy to build as possible, so that users can can build them on their own with minimal fuss.
Generally it's not possible to link against libraries built with different compilers, different versions of the same compiler, and even different settings of the same compiler version and get a working application. (Although it might work for specific subsets of the language and std library.) There is no standard binary interface for C++ - not even one for some common platform as there are in C.
To achieve that, you either need to wrap your library in a C API or you will have to ship a binary for every compiler, compiler version, and compiler setting you want to support.
If your library project is a static library, then, you'll have to supply a build for every Visual Studio version that you want your users to be in. In the example you gave, that equates to providing both a VS2005 and a VS2008 library.
If your library project is a dynamic library, then, you evade the problems somewhat, but, it means that users will need to make sure that they use the 'Microsoft C Runtime' that's compatible with your build environment. You can eliminate that criteria should you statically link the 'Microsoft C Runtime' into your dynamic library.