如何从 dll 导出 C++ 类?[复制]

How to export a C++ class from a dll? [duplicate]

提问人:Apoorva sahay 提问时间:7/27/2011 最后编辑:Bo PerssonApoorva sahay 更新时间:6/13/2014 访问量:89815

问:

我有一个类,它有两个重载函数。如何从 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 可视化 C++ DLL

评论

1赞 Frerich Raabe 7/27/2011
令我惊讶的是,我没有找到与此重复的现有问题。我本来以为这是一个相当普遍的问题。
0赞 Ajay 7/27/2011
检查:stackoverflow.com/questions/6620791/exporting-classes-to-dlls

答:

53赞 Frerich Raabe 7/27/2011 #1

一种常见的方法是使用单个宏(我们称之为宏),该宏可以扩展为或取决于是否设置了某种“立即构建DLL”定义,如下所示:EXPORTdllimportdllexport

#ifdef MAKEDLL
#  define EXPORT __declspec(dllexport)
#else
#  define EXPORT __declspec(dllimport)
#endif

class EXPORT xyz {
  // ...
};

这个想法是,在生成 DLL 时,将添加到预处理器定义中。这样,所有代码都将被导出。链接到 DLL(因此包含此头文件)的客户端根本不需要执行任何操作。通过不定义,它们将自动导入所有代码。MAKEDLLMAKEDLL

这种方法的优点是,正确获取宏的负担从许多(客户端)转移到 DLL 的作者身上。

这样做的缺点是,当按原样使用上述代码时,不再可能将代码直接编译到某个客户端模块中,因为不可能将宏定义为无。为了实现这一点,你需要有另一个检查,如果为真,则将 EXPORT 定义为无。EXPORT

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

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

评论

5赞 Tobias Langner 7/27/2011
请记住,Mehrdads的答案是正确的,因为导出的类仅适用于此特定的编译器版本和编译器设置。甚至不允许混合使用Debug和Release(例如,使用Release dll的Debug客户端)。
3赞 foraidt 7/27/2011 #2

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

然后在库的代码中执行如下操作:

#ifdef MY_DLL_EXPORT
#  define DLL_API __declspec(dllexport)
#else
#  define DLL_API __declspec(dllimport)
#endif


class DLL_API some_class { /*...*/ }
14赞 weekens 7/27/2011 #3

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

我可能对这个例子是错误的(那是很久以前的事了),但这里它应该大致是什么样子的:

头文件 (.h):

class MyClass { ... };

extern "C" DLL_API MyClass* createMyClass();

源文件(.cpp):

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

在编译时定义MY_DLL_EXPORT,请参阅 foraidt 的答案示例。

评论

4赞 holgac 7/27/2011
这是实现它的最简单方法。但不要忘记将工厂函数放在 extern “C”{} 语句中。C++ 的名称修改可能会阻止您从 dll 加载函数。
0赞 Apoorva sahay 7/27/2011
你能给我举个例子吗
8赞 SridharKritha 6/13/2014 #4

另一种选择:

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

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

属性 -> 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 { 
             //.... 
  }