Building a .DLL
可以用App Wizard来实现以MFC为基础的.DLL.选择"File | New",在"Projects"标签上,选择"MFC AppWizard (.DLL).",为你的工程选一个名字,然后单击"OK".在下一个屏幕,选择建立一个MFC扩展的.DLL,或者正规的.DLL"using shared MFC .DLL"(就是动态连接到MFC),或者正规的.DLL(静态的连接到MFC).选择其中一个,按"Finish".
App Wizard新建立的.DLL没做任何事.编译新的.DLL,但是它不导出任何类和函数,本质上来说,没有任何用,你现在有两个工作:
1.增加函数.
2.修改客户端来调用你的.DLL.
Export a Class
上面提到,只有MFC的扩展.DLL能导出MFC/C++类.假设你建立了一个扩展的.DLL,你可以通过从另一个工程加入.cpp和.h文件来创建一个类,也可以在你的工程中创建新类.要导出这个新类,你必须在类的声明前加一个宏"AFX_EXT_CLASS",像这样:
class AFX_EXT_CLASS CMyClass
{
//class declaration goes here
};
_declspec(dllexport) int x;
就可以导出变量,为客户端应用.下面说的很重要:你只能导出全局的实例或者变量.局部的实例或者变量当它们跑出作用域,就会停止生存.如果用下面的方法,将不会正常工作:
MyFunction( )
{
_declspec(dllexport) CMyClass myObject;
_declspec(dllexport) int x;
}
一旦实例或者变量跑出作用域,它们将停止生存.
Export a function
导出函数和导出变量是很相似的.你可以简单的在函数前面加上"_declspec(dllexport)"
_declspec(dllexport) int MyExportedFunction(int);
这就是导出的全部.记住,只有MFC扩展的.DLL能导出C++函数或者以MFC的数据类型为参数或者返回值.正规的.DLLs只能导出C-style函数.
Using the .DLL in a client application
一个.DLL不能运行它自己.它需要客户端导入它,调用它的接口.
当你编译你的.DLL时,编译器创建两个很重要的文件: .DLL文件和.lib文件.你的客户端需要这两个文件.你必须拷贝它们到客户端的工程文件夹.
除了.DLL和.lib文件,你的客户端还需要要导出的类,函数,实例和变量所在的头文件.要导出函数时要加"_declspec(dllexport)"声明.现在要导入了,就要加入"_declspec(dllimport)"声明.如下:
_declspec(dllimport) CMyClass myObject;
_declspec(dllimport) int x;
_declspec(dllimport) int MyExportedFunction(int);
为了可读性,我们可以这样写:
#define DLLIMPORT _declspec(dllimport)
DLLIMPORT CMyClass myObject;
DLLIMPORT int x;
DLLIMPORT int MyExportedFunction(int);
现在你声明了你的实例,变量和函数,可以用了.:)
要导出整个类,你必须将整个.h头文件拷过来..DLL和客户端要有唯一的关于此导出类的头文件.记住,类的声明要加上: AFX_EXT_CLASS 宏.
一旦你建立了客户端,你已经准备给客户用了,你应该给他们你的Release可执行文件和Release的.DLL.不用给用户.lib文件..DLL可以放在客户程序的目录,或者系统目录.还有上面提到的,你要提供正确的MFC代码库的.DLL.这个.DLL是你的机器装Visual C++时候用的.
class AFX_EXT_CLASS CMyInterface
{
class CMyClass; //forward declaration of CMyClass
CMyClass *m_pMyClass;
public:
CMyInterface( );
~CMyInterface( );
int FunctionA(int);
int FunctionB(int);
};
这份头文件将用在.DLL和客户端程序.注意,前面的声明意味着没有CMyClass的备份也可以编译.
在.DLL内部,这样实现CMyInterface:
CMyInterface::CMyInterface( )
{
m_pMyClass = new CMyClass;
}