I want to write SDK using Visual C++ 2010, which can be used by VC++ 2010 clients, and also old VC++ version clients. Let's say, I want to have it compatible for 2005 and 2008 versions. SDK contains several h, lib and dll files. Libraries have exported C++ classes and global functions. Public SDK interface (h-files) doesn't contain any feature that is not supported in previous VC++ versions. Internal SDK implementation may contain such features (like Lambda expressions, rvalue references etc.).
Some public SDK methods have callback interface parameters. Callback interfaces are defined in my h-files, implemented in the client code and passed to my methods. Can this be a problem?
I made several small tests and found that it works. Does anyone know any problem with using VC++ 2010 SDK by C++ clients, written in old VC++ versions?
Key principles:
You cannot expose any objects from the standard C++ library (std::string etc), their layout is not compatible
You cannot use exceptions, SEH is okay
You cannot return any pointers that require the client code to release the pointed-to resource
You should build with /MT so the client doesn't have a headache digging up the required CRT version
You are generally okay with object layout between 2003 through 2010 as long as you can ensure it is not affected by compiler settings other than /Zp. Virtual inheritance has been troublesome. Verify that sizeof yields the same size regardless of the selected configuration.
COM is a good way to ensure maximum compatibility.
Related
I have following 2 questions wrt to Windows SDK and Platform toolsets and C/C++ runtime library.
a) What is the relation of Windows SDK with C/C++ runtime and platform toolset?
Is it correct to say that BOTH C++ runtime libraries & platform toolsets are provided by Windows SDK?
Since we mostly deal with Platform toolsets from within the Visual Studio project settings, so want to understand that whether under the hood does the Visual Studio controls the C++ runtime library and platform toolset versions by installing the required version of Windows SDK?
b) Another thing i wanted to clarify was that if it is correct to say one version of platform toolset can work with different version of Windows SDK OR these are totally unrelated?
eg. in my Visual Studio i see that 'Windows SDK version' is Windows 10 and Platform toolset is v142. Can i set the 'Windows SDK version' to Windows 8.1 and keep the toolset as v142? If yes, then what does it mean?
This is confusing me a lot and i can't seem to get the correct picture with so many different explanations from different people.
TL;DR: If you are using Visual C++, and use the standard REDIST instructions from Microsoft Docs, then these details shouldn't really matter to you.
With VS 2015 and later, the "C/C++ Runtime" has been refactored into three pieces:
UCRTBASE.DLL is part of the OS and serviced through Windows Update. There are 'down-level' versions of it included in the Visual C++ REDIST package, but generally you should think of this as the "OS" part. This is the "C Runtime". These headers, import libraries, and are in the Windows 10 SDK. You can find the source for it there as well C:\Program Files (x86)\Windows Kits\10\Source\<version>\ucrt.
MSVCP*.DLL This is the "C++ Runtime" library, basically stuff like std::vector et al. The headers, import libraries, and such are in the Visual C++ product. You can find the source to it on GitHub per this blog post.
VCRUNTIME*.DLL has the entry-points needed at runtime for the Visual C++ compiler language features.
There are also a few auxiliary libraries as well for specific scenarios:
VCCORLIB*.DLL is used for C++/CX extensions (a.k.a. /ZW)
VCAMP140.DLL is used for C++ AMP
VCOMP140.DLL is used for OpenMP
CONCRT*.DLL is used to implement C++11 <thread> on Windows XP (not used on newer versions of Windows; it's delay loaded if required)
See this blog post and this one.
Essentially the C runtime (the UCRTBASE) part is a simple extern "C" interface so the ABI is well-defined, and thus is usable with multiple versions of Visual C++ and even other compilers. Exactly which version of the UCRT you are using is therefore primarily depending on the OS and the Windows 10 SDK you are using via WindowsTargetPlatformVersion. You can applocal deploy UCRT as well per this blog.
The C++ Runtime (MSVCP*.DLL) includes a lot of inlines and exposed memory layouts, and historically there was a breaking change between between Visual C++ versions. That said, for VS 2015 Update 3, VS 2017, and VS 2019 the VC team has made a point of keeping 'binary compatibly' here meaning that if you have a static library that uses C++ std namespace components from a PlatformToolset of v140/v141, it will successfully link with a later version of Visual C++ up through v142. It's not clear that this will hold in the future, but it is true for this particular set of releases per Microsoft Docs.
The VCRUNTIME*.DLL needs to match the version of the Visual C++ compiler you are using to build the final link, so this is very much intended to match your PlatformToolset.
It looks like std::string is a header only file at Community/VC/Tools/MSVC/?/include/xstring, and all generated code should be included inside a build target.
If I'm correct, how does Microsoft guarantee that the next Visual Studio version doesn't change xstring and the std::string internal structure?
Update 1:
I got many downvotes for this question so let me explain why I decided to ask it.
I'm faced with strange crash, and I can not understand why this happen.
I use latest Qt 5.13.0 (MSVC2017_x64) and also I have some external libraries compiled with Visual Studio 2017. All have /MDd, I checked this with dumpbin util.
When I try to run any code that invokes Qt library and std::string, I'm getting wrong result (and crash at the end).
Here is very simple example:
#include <QApplication.h>
int main(int argc, char** argv) {
QString s1("Test");
std::string s2 = s1.toStdString(); // here we have s2 variable with wrong internal structure
return 0;
}
My idea was that QtCore DLL library has std::string with internal structure not compatible with std::string from Visual Studio 2017. But Qt was created with Visual Studio 2017 (maybe not same as my current Visual Studio, because there was several minor releases), so I decided to ask here if they are compatible or not.
Update 2:
Problem was in _ITERATOR_DEBUG_LEVEL. Looks like Qt was compiled with level 2 and all my external libraries and application were compiled with level 0.
This option affects internal structure of many C++ standard library classes and introduce such side effects. So when we are inside toStdString() and create std::string, we have level 2 and one internal structure. When we are in application code, we have level 0 and another internal structure. We assign object with one internal structure to object with another.
Anyway now I have better understanding of some internals.
how does Microsoft guarantee that the next Visual Studio version doesn't change xstring and the std::string internal structure?
Because they make a decision to guarantee that, or to not guarantee that.
For example, Visual Studio 2015 to 2019 are binary compatible.
That's a decision that was made, to do that. The result, if what you say is true, is that some of the implementation specifics of std::string on that platform are frozen. This is not unusual for libraries. libstdc++'s std::list::size was non-compliant to C++11 for many years, because they could not add a needed member variable without breaking binary compatibility.
In short, this is basically a project management decision, and if they ever change the header in a way that breaks things, they will tell you that binary compatibility has been broken and you need to rebuild and relink things accordingly.
As for your Qt issue, it does smell like a binary compatibility issue. But you say that both Qt and your application have been built in Visual Studio 2017 with /MDd, which would appear to rule that out. I would ask the Qt community for further help, possibly with slightly more information about your environment and about where you obtained Qt. Also ensure that you're using the version of Qt that's intended — perhaps there are multiple installations? Which one's on your include path?
Is std::string header only in Visual Studio?
Not entirely, it also depends on parts of the Standard C++ library that are implemented in Microsoft's Visual C++ Runtime. Building a binary with MSVC requires the VC++ runtimes to be linked. Only static libraries may be built without linking to a runtime, and then you must be careful to include none of the headers that require the runtime.
Is the std::string header only in Visual Studio?
(I originally read the headline this way.)
std::string is part of the C++ standard.
To use std::string on any platform that supports standard C++, you should use #include <string>. It is a standard header available with pretty much any C++ compiler.
Every compiler or platform may implement the standard in its own way though. For example with MSVC you can see that xstring is how Microsoft implements std::string under the hood. If you include xstring.h directly you are writing code that depends on the version of MSVC that provides that header. That code would not be portable to other compilers.
If I'm correct, how does Microsoft guarantee that the next Visual Studio version doesn't change xstring and the std::string internal structure?
Microsoft does not guarantee that the next Visual Studio version will have the same std::string internal structure. In the past the implementation of the standard library has changed with every VC++ runtime release, which is why Windows users end up having dozens of VC++ runtime versions installed in their Add/Remove programs list.
Thankfully Microsoft has given us a guarantee that Visual Studio 2015, 2017, and 2019 all use a binary-compatible C++ runtime. This means that binaries built using the standard library provided in Visual Studio 2015 are compatible with binaries built using 2017 and 2019 too. There is no guarantee (yet) that a future version of Visual Studio will not change the VC++ runtime implemenation again.
I have written a dll in visual studio community 2017. To be used as a general purpose library. Which could be ideally used for any c++ program for any compiler.
How will I best deploy it. (An installer)
In Visual Studio, I can simply add the project and reference it through settings in my IDE, but for it to work in any IDE, what kind of installer project should i use and what all files should be included and how.
You can't deploy a C++ DLL for all compilers. C++ doesn't have an ABI. Not even MSVC++ is compatible across versions, let alone compilers from different vendors.
The Windows solution for binary compatibility is COM. Conveniently, MSVC++ will use the COM ABI for classes that inherit from IUnknown, although you'll also have to adhere to other COM rules for full compatibility. E.g. you can't rely on dynamic_cast, you need QueryInterface.
One of the legacy application which build in 2010 visual studio(native application) need to be upgraded its one of the DLL which build in visual studio 15, is this possible?
If the interface uses types from the C++ Standard Library, such as std::string, it's unlikely to work. These types generally come from the C++ runtime, and the two versions have different runtime libraries.
If the interface uses LPCSTR, the implementation can use any string library internally (standard, Qt, etc)
I write the plugins for AutoCAD. If I write the managed (i.e. .net) plugins, then I can use any Visual Studio version which can work with .NET Framework version which are used by AutoCAD (it is very convenient):
AutoCAD 2009 can use .NET 3.0, 3.5
AutoCAD 2010 can use .NET 3.5.
...
AutoCAD 2016 can use .NET 4.5, 4.5.1
So, through Visual Studio 2013 I can write the .net plugins for AutoCAD 2009-2016.
But sometimes I need to write unmanaged plugins for AutoCAD, because its managed .net API covers unmanaged API (ObjectARX SDK) not complettely. ObjectARX is API for C++. At this case I can't use the same Visual Studio for each AutoCAD version. For example, I am to use VS 2005 for AutoCAD 2009 plugins writting. Therefore I have installed VS 2005-2013 on my virtual machine. It is very unconvenient in my opinion.
I know, this problem exists because the standard of C++ functions naming is not exist and each version of VS has own rules of the name generation for the functions which aren't marked by external "C".
But why this standard is not exist still? What the reason of it? I am sure this reason is exists. Such behaviour is unconvenient is not for me only (I asked other programmers about it). But they don't know why each new VS version has own rules of C++ function naming and why standard of nameing of C++ functions is not exist.
Thank you.
A standard does exist, see https://mentorembedded.github.io/cxx-abi/abi.html#mangling
But not all compilers use it, because they have their own mangling conventions that they have used for many years, and they don't want to change them for various reasons.
In your case the differences between different versions of Visual Studio are not just name mangling, there are changes in the C++ runtime library and the standard library.