• 浅谈Windows中DLL导出类


    一般的DLL导出类方法,一个简单的例子:

    dllExample.h:

     1 #pragma once
     2 
     3 #ifdef DLL_EXPORTS
     4 #define DLL_API __declspec(dllexport)
     5 #else
     6 #define DLL_API __declspec(dllimport)
     7 #endif
     8 
     9 class DLL_API ExportClass
    10 {
    11 pirvate:
    12     int x;
    13 public:
    14     void foo();
    15 };

    dllExample.cpp:

    1 #define DLL_EXPORTS
    2 #include "dllExample.h"
    3 
    4 void ExportClass::foo()
    5 {
    6     //do something...
    7     return;
    8 }

    而外部代码只需要包含头文件,就会自动导入ExportClass的定义。
    编译时连接该DLL对应的lib,运行时提供DLL文件,即可正常运行。

    不过这种简单的DLL导出存在一个限制,如果我们导出的类中含有非C++基础类型:

    dllExample.h:

     1 #pragma once
     2 
     3 #ifdef DLL_EXPORTS
     4 #define DLL_API __declspec(dllexport)
     5 #else
     6 #define DLL_API __declspec(dllimport)
     7 #endif
     8 
     9 class DLL_API ExportClass
    10 {
    11 pirvate:
    12     std::string x; //此处的string类型导出是不安全的
    13 public:
    14     void foo();
    15 };

    我们知道, 对于STL,微软为每个版本的VS都有不同的实现,VS2008(VC90),VS2010(VC100),VS2013(VC120)。
    由于不同的STL的实现,我们不能在不同的版本见直接传递std::string, 否则运行期可能出现不可预知的错误。
    而事实上我们在ExportClass中的std::string x变量是不希望被外部直接使用的,也就是并没有export的必要,事实上,不建议让dll向外导出任何关于非C++基础类型的定义。
    但是由于ExportClass需要向外导出(因为需要使用foo()函数),应该如何处理这样的矛盾呢?

    对于这样的问题,我们需要使用C++的抽象类(其实就是java中的interface概念)来解决:
    我们需要:
    1. 申明一个只有纯虚函数和C++基础类型的基类,所有需要向外部导出的定义都包含在该类中。
    2. 申明另一个类,继承该基类。
    3. 实现一个返回基类函数指针的getInstance函数,即返回一个派生类实例的工厂方法。
    4. 在外部代码中,通过多态机制访问该类。

    dllExample.h:

     1 #pragma once
     2 
     3 #ifdef DLL_EXPORTS
     4 #define DLL_API __declspec(dllexport)
     5 #else
     6 #define DLL_API __declspec(dllimport)
     7 #endif
     8 
     9 class DLL_API ExportInterface
    10 {
    11 public:
    12     virtual void foo() = 0;
    13 };
    14 
    15 extern "C" DLL_API ExportInterface*  getInstance();
    16 
    17 #ifdef DLL_EXPORTS  //我们并不需要向外导出该类的定义,在外部代码编译时,也不需要包含此类的定义。
    18 class ExportClass: public ExportInterface
    19 {
    20 pirvate:
    21     std::string x; //由于外部代码对此不可见,此处的std::string是安全的。
    22 public:
    23     void foo(); //函数体在dllExample.cpp中实现
    24 };
    25 #endif

    dllExample.cpp:

    #define DLL_EXPORTS
    #include "dllExample.h"
    
    extern "C" DLL_API ExportInterface* getInstance()
    {
        ExportInterface* pInstance = new ExportClass();
        return pInstance;
    }
    
    void ExportClass::foo()
    {
        //do something...
        return;
    }
  • 相关阅读:
    个人阅读作业
    软件工程基础/个人项目1
    个人阅读作业3
    个人阅读作业2
    代码复审
    软件工程:结对编程1
    个人阅读作业
    软工作业1:单词统计
    有关敏捷开发的一点感想[110617班 刘耀先]
    Pair Project: Elevator Scheduler [电梯调度算法的实现和测试][关于电梯调度算法的附加思考]:刘耀先-11061183,罗凡-11061174
  • 原文地址:https://www.cnblogs.com/JingJ/p/4442286.html
Copyright © 2020-2023  润新知