Re: Assistance required, exporting a class from a DLL
Alex Blekhman wrote:
In order to make robust DLL interface that you will able to call
from different clients you need to declare abstract class without
data members and with all member functions being pure virtual.
For some definitions of robust, that is. The approach which e.g. Boost,
STLport and the MFC are taking is to provide different versions of the
library for the different uses. For those that export an interface related
to the win32 API you need to provide ANSI and UNICODE builds. Further, you
need debug and release builds. Optionally, you might want to create
diagnostic builds. Then, of course, there are dynamically and statically
linked builds (though I personally don't care for the latter). This
multiplied by the number of compilers to support and you have a rather
robust system, too.
This seems like a lot of work and it initially is, but it allows you to not
introduce any code that only works around linking quirks into your code. In
fact it allows a completely 'natural' use of the library code, including
important things like exceptions. Further, selecting the right lib should
then be done using #pragma comment(lib, ..) and by checking preprocessor
macros, which saves much time when using the library, too.
You can find the more elaborate study here:
"HowTo: Export C++ classes from a DLL"
http://www.codeproject.com/KB/cpp/howto_export_cpp_classes.aspx
There is one claim in there that is simply wrong:
| in order to export a C++ class successfully, a developer is
| required to export all the relevant base classes and all the
| classes that are used for the definition of the data members.
Two things here:
1. It is not necessary to export the classes of all data members, only that
they are available to the one that includes the library. If it was
necessary, you would also get an error (hopefully) and not a warning you
can ignore.
Note the fine distinction between exporting and making available: In
particular for cases like std::map<>, it means that since it is available
to both the library and the code that uses it (you must include the header
to use it in an exported interface), there is no need to do anything
further, in particular not to export it from your DLL. It would even be
wrong to export it, since that would mean that another library exporting
it, too, would cause a conflict.
2. I know that I exported a class derived from std::pair<unsigned,unsigned>
from a library, and the compiler actually exported not only symbols of the
derived class but also symbols of the baseclass. I personally consider that
a bug, and I believe it also isn't present in all MS compilers, but I since
then simply changed the interface to not use std::pair, because it was
trivial to do and less work than a proper fix or more complicated
workaround.
One more suggestion on your article: your suggestion to use a pure virtual
interface and using a Release() function instead of the destructor would
actually benefit from having a protected (nonvirtual) destructor. This
would make it impossible for clients to invoke it accidentally.
Uli
--
C++ FAQ: http://parashift.com/c++-faq-lite
Sator Laser GmbH
Gesch??ftsf??hrer: Thorsten F??cking, Amtsgericht Hamburg HR B62 932