Re: LNK2019 unresolved external symbol / how to ignore dllimport?
Tim Roberts wrote:
"Frederiek" <fd_news@hotmail.com> wrote:
class DBP_EXPORT AAA_SSF
{
public:
virtual ~AAA_SSF() { }
// other members
protected:
AAA_SSF() { }
// other members
};
DBP_EXPORT is a define that depends on whether the header file is used
to build a library, or in a program using the library.
We seem to be seeing more and more examples of the technique of exporting
an entire C++ class from a DLL. This is a dramatically bad idea.
Such a DLL is tightly bound to the version of C++ you are using. The C++
name mangling scheme has changed at least once in the history of Visual
C++, and changes to the C++ language will probably require it to change
again. In that case, your DLL will be useless.
It's not just the name mangling, but the whole compiler ABI. The name
mangling is only a way to ensure that incompatible ABIs don't cause runtime
errors but linker errors. Another thing is dependent libs, in particular
the C++ standardlibrary. Anyhow, smart people encode the compiler-ABI
(which is basically the name of the compiler) into the DLL, just like they
add e.g. a 'd' for the debug versions. Using #pragma comment(lib,...) and
some preprocessor use this then works without problems.
A much better design is to separate the interface and the implementation.
Create a pure virtual base class which defines the functions and methods
you expect to support. Create an implementation which derives from your
interface, that is hidden to the outside world inside the DLL. Create a
NON-METHOD object factory which returns an instance of your class.
Example:
class AAA_SSF
{
// Pure virtual base class -- an interface.
// This declaration is exposed to user applications.
}
class AAA_SSF_impl : pubic AAA_SSF
{
// Class which implements the AAA_SSF functions. This
// declaration is not exporsed to user applications.
}
extern "C" AAA_SSF* __declspec(dllexport)
Create_AAA_SSF()
{
return new AAA_SSF_impl;
}
Now, your DLL has exactly one export (Create_AAA_SSF). The import library
doesn't have to change at all when you add or remove members from the
interface or the implementation. Your name has standard C mangling, and
can even be called from C, just like a COM interface.
Okay, but unless you also export every memberfunction in a C-style way you
don't gain anything, you can call the factory function, but you can't call
any methods because their mangled name or the implementation of the vptr
may be different. Also, you lose things like overloading and simple value
semantics. IMHO, exporting things via a C interface makes most sense when
you use explicit loading of plugins.
Uli