【问题标题】:How to export a C++ class from a dll? [duplicate]如何从 dll 中导出 C++ 类? [复制]
【发布时间】:2015-12-21 06:39:23
【问题描述】:

我有一个有两个重载函数的类。如何从 dll 中导出它以及如何由其他 C++ 类使用它?我的班级是这样的:

#define DECLDIREXP __declspec(dllexport) 

#define DECLDIRIMP __declspec(dllimport)


class DECLDIREXP xyz 

{

public: 
          void printing();
          void printing(int a);
};  

using namespace std; 

void xyz::printing()
{
        cout<<"hello i donot take any argument";
}


void xyz::printing(int a)
{
        cout<<"hello i take "<< a <<"as argument";
}

【问题讨论】:

标签: c++ visual-c++ dll


【解决方案1】:

另一种选择:

对项目使用默认定义的宏本地

您可以在以下位置查看项目本地默认定义的宏:

属性 -> C/C++ -> 预处理器 -> 预处理器定义。

示例:

假设您的项目名称是:MyDLL

该项目的默认宏本地:MYDLL_EXPORTS

 #ifdef  MYDLL_EXPORTS 
    /*Enabled as "export" while compiling the dll project*/
    #define DLLEXPORT __declspec(dllexport)  
 #else
    /*Enabled as "import" in the Client side for using already created dll file*/
    #define DLLEXPORT __declspec(dllimport)  
 #endif


  class DLLEXPORT  Class_Name { 
             //.... 
  }

【讨论】:

    【解决方案2】:

    我记得,通常情况下,您导出的不是一个类,而是一个创建类的新实例并返回一个指针的工厂函数。类声明驻留在编译时的头文件中。

    我可能对这个例子有误(那是很久以前的事了),但它应该是这样的:

    头文件(.h):

    class MyClass { ... };
    
    extern "C" DLL_API MyClass* createMyClass();
    

    源文件(.cpp):

    DLL_API MyClass* createMyClass() {
        return new MyClass();
    }
    

    编译时定义MY_DLL_EXPORT,见foraidt的回答例子。

    【讨论】:

    • 这是最简单的实现方式。但不要忘记将工厂函数放在 extern "C"{} 语句中。 C++ 的名称修改可能会阻止您从 dll 加载函数。
    • 你能给我举个例子吗
    【解决方案3】:

    一种常见的方法是使用单个宏(我们称之为EXPORT),它可以扩展为dllimportdllexport,具体取决于是否设置了某种“立即构建DLL”定义,就像这样:

    #ifdef MAKEDLL
    #  define EXPORT __declspec(dllexport)
    #else
    #  define EXPORT __declspec(dllimport)
    #endif
    
    class EXPORT xyz {
      // ...
    };
    

    这个想法是,在构建 DLL 时,将 MAKEDLL 添加到预处理器定义中。这样,所有代码都将被导出。链接到您的 DLL(并因此包含此头文件)的客户端根本不需要做任何事情。通过不定义MAKEDLL,他们将自动导入所有代码。

    这种方法的优势在于,正确处理宏的负担从众多(客户端)转移到了 DLL 的作者身上。

    这样做的缺点是,当按原样使用上面的代码时,不再可能直接将代码编译到某个客户端模块中,因为不可能将EXPORT 宏定义为空。为此,您需要进行另一项检查,如果为真,则将 EXPORT 定义为空。

    关于一个稍微不同的主题:在许多情况下,不可能(或不希望!)导出这样的完整类。相反,您可能只想导出所需的符号。例如,在您的情况下,您可能只想导出两个公共方法。这样,所有私有/受保护的成员都不会被导出:

    class xyz
    {
    public: 
        EXPORT void printing();
        EXPORT void printing(int a);
    };
    

    【讨论】:

    • 请记住,Mehrdads 的回答是正确的,因为导出的类仅适用于这个特定的编译器版本和编译器设置。甚至不允许混合调试和发布(例如,使用 Release dll 调试客户端)。
    【解决方案4】:

    在编译库时,您应该定义一个宏(命令行预处理器定义),我们称之为MY_DLL_EXPORT

    然后在你的库的代码中做这样的事情:

    #ifdef MY_DLL_EXPORT
    #  define DLL_API __declspec(dllexport)
    #else
    #  define DLL_API __declspec(dllimport)
    #endif
    
    
    class DLL_API some_class { /*...*/ }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-09-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-25
      相关资源
      最近更新 更多