Re: passing stl through dll
"Konran Udo Gerber" wrote:
Thanks Alex - the 1. Easy way did not work for me as I already
disabled C4251 conditionally (for the STL includes, typedefs,
declarations and defines).
I think the most practical solution is to stop exporting STL
classes alltogether. Just use them as they are and disable C4251
warning.
So I tried 2. Hard way, which works fine for <vector> and the
<string> stuff but I'm struggling with <hash_map>.
That's why I called it a hard way. For `stdext::hash_map' class
you will need to export manually an insane number of classes. Most
of them are internal classes of the Standard Library that may
change with any following service pack. This solution is somewhat
practical for small or relatively simple classes like
`std::vector' or `std::string'. For complex classes like
`std::hash_map' you will need to export a half of the STL code.
1. The define _STATIC_CPPLIB has to be placed in the DLL project
and also in the client EXE project?
No, you don't need it for the EXE. It's enough to put the define
for the DLL only. This macro affects only those standard templates
that are instantiated and placed in "msvcpXX.dll". Not all
templates are pre-instantiated by MS, but only the most popular
ones like `std::string'. You can open this DLL with Dependency
Walker tool to see full list of contained instantiations.
2. What does template instantiation exactly mean? Is it just a
definition of an interface to a specific class with all
requested types filled in? Does it produce any binary code (as
it is said that no objects are created)?
Yes, template instantiation means that compiler will use specific
types and will produce a binary code. The important thing to
understand is that templates are not code. They become a C++ code
when developer instantiates them with real compilable types.
That's why MS decided to put some popular instantiations in
separate DLL. They thought that it will save you a couple of KB's
in a resulting EXE. Because everybody uses `std::string',
`std::cout' et al. But you can always discard these instantiations
with _STATIC_CPPLIB if you want and make your own.
3. the lines:
template class STL_API std::allocator<std::basic_string<char> >;
template class STL_API std::vector<std::basic_string<char> >;
are conditionally prepended with "extern" in the reference doc
http://www.unknownroad.com/rtfm/VisualStudio/warningC4251.html -
you did not differentiate between "extern" and "auto" for EXE
and DLL code. Is it OK to instantiate the templates in both
cases?
I tried it first with `extern', but the compiler complained that
this is non-standard extension, so I threw away the `extern'. It
seems that the code works anyway.
For <hash_map> it is hard to find the instantiations necessary
for the compiler - I get C4251's again in the EXE code beside
the warning suppression already done.
It means that part of the headers don't see the pragma. You may
tryu to disable it on project level in project settings.
If nothing helps, then the common approach for this is to make a
wrapper class that uses Pimpl idiom and doesn't expose any STL
containers. You can read more about Pimpl idiom here:
"Compilation Firewalls"
http://www.gotw.ca/gotw/024.htm
HTH
Alex