Re: problem using self built DLL
On 20 Apr 2007 11:47:16 -0700, wanwan <ericwan78@yahoo.com> wrote:
I made an MFC extension DLL, but I couldn't get it working on the
client application. Can somebody please tell me what I did wrong in
the procedure:
1. I started an MFC extension DLL project called "MyDll". I added a
class called "MyClass" and added the keyword AFX_EXT_CLASS in the
class declaration in the header file.
You should use your own macro instead of AFX_EXT_CLASS, because otherwise
your DLL won't be able to #include headers from another DLL that also uses
AFX_EXT_CLASS, i.e. one extension DLL won't be able to use another
extension DLL. Below is a message I've posted several times concerning the
right way to use __declspec:
In some DLL header file, which the other DLL headers #include, write the
following, replacing "X" with the name of your DLL, making sure it has a
reasonable chance of being unique:
#ifdef COMPILING_X_DLL
#define X_EXPORT __declspec(dllexport)
#else
#define X_EXPORT __declspec(dllimport)
#endif
Then #define COMPILING_X_DLL only in that DLL's project. This method can be
used by multiple DLLs, a big advantage over AFX_EXT_CLASS, and since the
macro names are unique, they don't conflict. Then you can do things like:
X_EXPORT void f();
class X_EXPORT MyClass
{
...
};
Look in the project's preprocessor options, and you may find the AppWizard
has already defined a suitable COMPILING_X_DLL macro for you.
2. I built the project and copied the files "MyDll.dll" and
"MyDll.lib" to the client project folder.
3. In the client project settings, I added the file MyDll.lib in the
linker - input section.
4. I made a MyDll.h file with the line: class AFX_EXT_CLASS MyClass;
This defines an incomplete type called MyClass. About all you can do with
it is use it to declare pointer and reference types.
5. I used #include "MyDll.h" in the cpp files where I need MyClass.
With the above steps, I expect MyClass to be defined. But when I use
the imported class it gave me the error:
error C2079: 'CClientApp::myobject' uses undefined class 'MyClass'
You need to #include the header that defines MyClass; IOW, you need to
#include the header that contains:
class AFX_EXT_CLASS MyClass
{
.... class definition
};
This means your DLL's header files (at least the ones that export things)
have to be available to the DLL clients. This gets to be a royal pain.
Typically I handle it all by defining my own "lib" and "include"
directories. In the project settings, I relocate the DLL output files to my
lib and rename them so they don't conflict, sort of like what MS does with
MFC42.DLL vs MFC42D.DLL and all the variants. Then I create subdirectories
in my "include" folder for each library and move their public headers
there. I add my "include" folder to the compiler's list and #include the
files with:
#include <libname/filename.h>
As for the .lib files, I add my "lib" directory to the linker's list and
use #pragma comment(lib) in the public DLL header files to select the right
libraries; this relieves me from having to add the libraries to each
project's linker settings. You can also add "lib" to the IDE's PATH list so
the DLL's will be available when you try to run your programs.
To tie all this together, I create a file "DeclSpec.h" for each DLL, and it
typically looks like this:
#pragma once
#ifdef COMPILING_X_DLL
#define X_EXPORT __declspec(dllexport)
#else
#define X_EXPORT __declspec(dllimport)
#endif
#ifndef COMPILING_X_DLL
# ifdef _DEBUG
# pragma comment(lib, "XD.lib")
# else
# pragma comment(lib, "X.lib")
# endif
#endif
Then every public DLL header file #includes "DeclSpec.h" first thing. It
gets more complicated when you have static library variants, Unicode
versions, etc, but that's the basic pattern.
--
Doug Harrison
Visual C++ MVP