zoukankan      html  css  js  c++  java
  • 编写DLL所学所思(2)——导出类

    2011.10.6

    烛秋

    一、导出类的简单方式

    这种方式是比较简单的,同时也是不建议采用的不合适方式。

    只需要在导出类加上__declspec(dllexport),就可以实现导出类。对象空间还是在使用者的模块里,dll只提供类中的函数代码。不足的地方是:使用者需要知道整个类的实现,包括基类、类中成员对象,也就是说所有跟导出类相关的东西,使用者都要知道。通过Dependency Walker可以看到,这时候的dll导出的是跟类相关的函数:如构造函数、赋值操作符、析构函数、其它函数,这些都是使用者可能会用到的函数。

    这种导出类的方式,除了导出的东西太多、使用者对类的实现依赖太多之外,还有其它问题:必须保证使用同一种编译器。导出类的本质是导出类里的函数,因为语法上直接导出了类,没有对函数的调用方式、重命名进行设置,导致了产生的dll并不通用。

    部分代码(DLL头文件):

    //2011.10.6
    //cswuyg
    //dll导出类,比较差劲的方法
    #pragma once
    #ifdef NAIVEAPPROACH_EXPORTS
    #define NAIVEAPPROACH_API __declspec(dllexport)
    #else
    #define NAIVEAPPROACH_API __declspec(dllimport)
    #endif
    
    
    
    //基类也必须导出,否则警告:
    class  NAIVEAPPROACH_API CBase
    {
    public:
        void Test();
    private:
        int m_j;
    };
    
    //也必须导出
    class NAIVEAPPROACH_API CDate
    {
    public:
        void Test2();
    private:
        int m_k;
    };
    
    class NAIVEAPPROACH_API CNaiveApproach : public CBase
    {
    public:
        CNaiveApproach(int i = 0);
        // TODO: add your methods here.
        void Func();
    private:
        int m_iwuyg;
        CDate m_dobj;
    };

    Demo代码见附件NaiveApproach部分。

    二、导出类的较好方式

    这种方式是比较合适的,跟com类似。

             结构是这样的:导出类是一个派生类,派生自一个抽象类——都是纯虚函数。使用者需要知道这个抽象类的结构。DLL最少只需要提供一个用于获取类对象指针的接口。使用者跟DLL提供者共用一个抽象类的头文件,使用者依赖于DLL的东西很少,只需要知道抽象类的接口,以及获取对象指针的导出函数,对象内存空间的申请是在DLL模块中做的,释放也在DLL模块中完成,最后记得要调用释放对象的函数。

             这种方式比较好,通用,产生的DLL没有特定环境限制。借助了C++类的虚函数。一般都是采用这种方式。除了对DLL导出类有好处外,采用接口跟实现分离,可以使得工程的结构更清晰,使用者只需要知道接口,而不需要知道实现。

      部分代码:

    (1)DLL头文件:

    //2011.10.6
    //cswuyg
    //dll导出类
    //dll跟其使用者共用的头文件
    #pragma  once
    #ifdef MATUREAPPROACH_EXPORTS
    #define MATUREAPPROACH_API __declspec(dllexport)
    #else
    #define MATUREAPPROACH_API __declspec(dllimport)
    #endif
    
    class IExport
    {
    public:
        virtual void Hi() = 0;
        virtual void Test() = 0;
        virtual void Release() = 0;
    };
    
    extern "C" MATUREAPPROACH_API IExport* _stdcall CreateExportObj();
    extern "C" MATUREAPPROACH_API void _stdcall DestroyExportObj(IExport* pExport);

    (2)导出类头文件:

    //2011.10.6
    //cswuyg
    //dll导出类
    // 实现类
    #pragma once
    
    #include "MatureApproach.h"
    
    class ExportImpl : public IExport
    {
    public:
        virtual void Hi();
        virtual void Test();
        virtual void Release();
        ~ExportImpl();
    private:
    };

             Demo代码见附件MatureApproach部分。

    三、总结

    导出类是比较简单的,比较容易混淆的概念上一篇总结已经说完了。本质上来说,跟导出函数没差别。使用VS2005自动生成的代码可以省去很多力气,比起以前做练习什么都是自己动手写方便多了。要注意一下工程的设置,熟悉它们的作用可以加快编程速度。

    Demo代码附件:

    https://files.cnblogs.com/cswuyg/%E7%BC%96%E5%86%99DLL%E6%89%80%E5%AD%A6%E6%89%80%E6%80%9D(2)(%E5%AF%BC%E5%87%BA%E7%B1%BB).rar

    参考资料:

    http://www.codeproject.com/KB/cpp/howto_export_cpp_classes.aspx

  • 相关阅读:
    preprocessing
    hist
    RabbitMQ
    线程池
    springmvc功能以及源码实现分析
    西瓜书第二章--模型评估与选择
    西瓜书第一章--绪论
    基于python的递归简述
    python小白学习之旅5
    python小白学习之旅4
  • 原文地址:https://www.cnblogs.com/cswuyg/p/DLL2.html
Copyright © 2011-2022 走看看