zoukankan      html  css  js  c++  java
  • MFC DLL向导(一)

        虽然能用DLL实现的东西都可以用COM来实现,但DLL的优点确实不少,它更容易创建。本文将讨论如何利用MFC来创建不同类型的DLL,以及如何使用他们。

    一、DLL的不同类型
        使用MFC可以生成两种类型的DLL:MFC扩展DLL和常规DLL。常规DLL有可以分为动态连接和静态连接。Visual C++还可以生成WIN32 DLL,但不是这里讨论的主要对象。
    1、MFC扩展DLL
       每个DLL都有某种类型的接口:变量、指针、函数、客户程序访问的类。它们的作用是让客户程序使用DLL,MFC扩展DLL可以有C++的接口。也就是它可以导出C++类给客户端。导出的函数可以使用C++/MFC数据类型做参数或返回值,导出一个类时客户端能创建类对象或者派生这个类。同时,在DLL中也可以使用DLL和MFC。
       Visual C++使用的MFC类库也是保存在一个DLL中,MFC扩展DLL动态连接到MFC代码库的DLL,客户程序也必须要动态连接到MFC代码库的DLL。(这里谈到的两个DLL,一个是我们自己编写的DLL,一个装MFC类库的DLL)现在MFC代码库的DLL也存在多个版本,客户程序和扩展DLL都必须使用相同版本的MFC代码DLL。所以为了让MFC扩展DLL能很好的工作,扩展DLL和客户程序都必须动态连接到MFC代码库DLL。而这个DLL必须在客户程序运行的计算机上。
    2、常规DLL
       使用MFC扩展DLL的一个问题就是DLL仅能和MFC客户程序一起工作,如果需要一个使用更广泛的DLL,最好采用常规DLL,因为它不受MFC的某些限制。常规DLL也有缺点:它不能和客户程序发送指针或MFC派生类和对象的引用。一句话就是常规DLL和客户程序的接口不能使用MFC,但在DLL和客户程序的内部还是可以使用MFC。
       当在常规DLL的内部使用MFC代码库的DLL时,可以是动态连接/静态连接。如果是动态连接,也就是常规DLL需要的MFC代码没有构建到DLL中,这种情况有点和扩展DLL类似,在DLL运行的计算机上必须要MFC代码库的DLL。如果是静态连接,常规DLL里面已经包含了需要的MFC代码,这样DLL的体积将比较大,但它可以在没有MFC代码库DLL的计算机上正常运行。

    二、建立DLL
        利用Visual C++提供的向导功能可以很容易建立一个不完成任何实质任务的DLL,这里就不多讲了,主要的任务是如何给DLL添加功能,以及在客户程序中利用这个DLL
    1、导出类
       用向导建立好框架后,就可以添加需要导出类的.cpp .h文件到DLL中来,或者用向导创建C++ Herder File/C++ Source File。为了能导出这个类,在类声明的时候要加“_declspec(dllexport)”,如:
    class _declspec(dllexport) CMyClass
    {
         ...//声明
    }
    如果创建的MFC扩展DLL,可以使用宏:AFX_EXT_CLASS:
    class AFX_EXT_CLASS CMyClass
    {
         ...//声明
    }
    这样导出类的方法是最简单的,也可以采用.def文件导出,这里暂不详谈。
    2、导出变量、常量、对象
       很多时候不需要导出一个类,可以让DLL导出一个变量、常量、对象,导出它们只需要进行简单的声明:_declspec(dllexport) int MyInt;
      _declspec(dllexport) extern const COLORREF MyColor=RGB(0,0,0);
      _declspec(dllexport) CRect rect(10,10,20,20);
    要导出一个常量时必须使用关键字extern,否则会发生连接错误。
    注意:如果客户程序识别这个类而且有自己的头文件,则只能导出一个类对象。如果在DLL中创建一个类,客户程序不使用头文件就无法识别这个类。
      当导出一个对象或者变量时,载入DLL的每个客户程序都有一个自己的拷贝。也就是如果两个程序使用的是同一个DLL,一个应用程序所做的修改不会影响另一个应用程序。
      我们在导出的时候只能导出DLL中的全局变量或对象,而不能导出局部的变量和对象,因为它们过了作用域也就不存在了,那样DLL就不能正常工作。如:
    MyFunction()
    {
          _declspec(dllexport) int MyInt;
          _declspec(dllexport) CMyClass object;
    }
    3、导出函数
    导出函数和导出变量/对象类似,只要把_declspec(dllexport)加到函数原型开始的位置:
    _declspec(dllexport) int MyFunction(int);
    如果是常规DLL,它将和C写的程序使用,声明方式如下:
    extern "c" _declspec(dllexport) int MyFunction(int);
    实现:
    extern "c" _declspec(dllexport) int MyFunction(int x)
    {
         ...//操作
    }
    如果创建的是动态连接到MFC代码库DLL的常规DLL,则必须插入AFX_MANAGE_STATE作为导出函数的首行,因此定义如下:
    extern "c" _declspec(dllexport) int MyFunction(int x)
    {
         AFX_MANAGE_STATE(AfxGetStaticModuleState());
         ...//操作
    }
    有时候为了安全起见,在每个常规DLL里都加上,也不会有任何问题,只是在静态连接的时候这个宏无效而已。这是导出函数的方法,记住只有MFC扩展DLL才能让参数和返回值使用MFC的数据类型。
    4、导出指针
    导出指针的方式如下:
    _declspec(dllexport) int *pint;
    _declspec(dllexport) CMyClass object = new CMyClass;
    如果声明的时候同时初始化了指针,就需要找到合适的地方类释放指针。在扩展DLL中有个函数DllMain()。(注意函数名中的两个l要是小写字母),可以在这个函数中处理指针:
    # include "MyClass.h"
    _declspec(dllexport) CMyClass *pobject = new CMyClass;
    DllMain(HINSTANCE hInstance,DWORD dwReason,LPVOID lpReserved)
    {
        if(dwReason == DLL_PROCESS_ATTACH)
        {
            .....//
        }
        else if(dwReason == DLL_PROCESS_DETACH)
        {
            delete pobject;
        }
    }
    常规DLL有一个从CWinApp派生的类对象处理DLL的开和关,可以使用类向导添加InitInstance/ExitInstance函数。
    int CMyDllApp::ExitInstance()
    {
        delete pobject;
        return CWinApp::ExitInstance();
    }

    三、在客户程序中使用DLL
        编译一个DLL时将创建两个文件.dll文件和.lib文件。首先将这两个文件复制到客户程序项目的文件夹里,这里需要注意DLL和客户程序的版本问题,尽量使用相同的版本,都使用RELEASE或者都是DEBUG版本。
       接着就需要在客户程序中设置LIB文件,打开Project Settings--->Link--->Object/library Modules中输入LIB的文件名和路径。如:Debug/SampleDll.lib。除了DLL和LIB文件外,客户程序需要针对导出类、函数、对象和变量的头文件,现在进行导入添加的关键字就是:_declspec(dllimport),如:
    _declspec(dllimport) int MyFunction(int);
    _declspec(dllimport) int MyInt;
    _declspec(dllimport) CMyClass object;
    extern "C" _declspec(dllimport) int MyFunction(int);
    在有的时候为了导入类,要把相应类的头文件添加到客户程序中,不同的是要修改类声明的标志:
    class _declspec(dllimport) CMyClass,如果创建的是扩展DLL,两个位置都是:
    class AFX_EXT_CLASS CMyClass。

  • 相关阅读:
    .NET Interop 工具集
    关于正弦波的算法
    Windows Phone 系列 本地数据存储
    Xaml cannot create an instance of “X”
    Windows Phone 系列 使用 MVVM绑定时无法获取当前值
    Windows Phone 系列 应用程序图标无法显示
    Windows Phone 系列 WPConnect无法上网的问题
    Windows Phone 系列 使用 Windows Phone 保存铃声任务
    WP7.5提交应用
    Windows Phone 系列 动态删除ObservableCollection
  • 原文地址:https://www.cnblogs.com/hehe520/p/6330141.html
Copyright © 2011-2022 走看看