【问题标题】:class declaration in C++C++ 中的类声明
【发布时间】:2020-10-16 07:47:17
【问题描述】:

我有一个班级: class RTC_EXPORT PeerConnectionInterface : public rtc::RefCountInterface { ... };

RTC_EXPORT 定义为

#ifndef RTC_BASE_SYSTEM_RTC_EXPORT_H_
#define RTC_BASE_SYSTEM_RTC_EXPORT_H_

// RTC_EXPORT is used to mark symbols as exported or imported when WebRTC is
// built or used as a shared library.
// When WebRTC is built as a static library the RTC_EXPORT macro expands to
// nothing.

#ifdef WEBRTC_ENABLE_SYMBOL_EXPORT
#ifdef WEBRTC_WIN

#ifdef WEBRTC_LIBRARY_IMPL
#define RTC_EXPORT __declspec(dllexport)  
#else
#define RTC_EXPORT __declspec(dllimport)
#endif

#else  // WEBRTC_WIN

#if __has_attribute(visibility) && defined(WEBRTC_LIBRARY_IMPL)
#define RTC_EXPORT __attribute__((visibility("default")))
#endif

#endif  // WEBRTC_WIN

#endif  // WEBRTC_ENABLE_SYMBOL_EXPORT

#ifndef RTC_EXPORT
#define RTC_EXPORT
#endif

#endif  // RTC_BASE_SYSTEM_RTC_EXPORT_H_

class RTC_EXPORT PeerConnectionInterface :public rtc::RefCountInterface {...}; 中的 RTC_EXPORT 有什么作用?

通常我们在 c++ 中将类定义为class Myclass{...}。附加的 MACRO 一般有什么作用?

【问题讨论】:

    标签: c++ dllimport dllexport


    【解决方案1】:

    除了德米特里的回答,我想添加一些实用工具来检查__declspec() 的影响。考虑以下源文件:

    // library.cpp
    __declspec(dllexport) int func(int x) { return 2 * x; }
    

    从您的 Visual Studio 安装中启动本机工具命令提示符 菜单。在那里,您可以使用以下命令编译并链接library.cpp 到 DLL:

    > cd <Directory containing library.cpp>
    > cl /c library.cpp
    > link library.obj /DLL /NOENTRY
    

    library.cpp 旁边应该有一个新创建的 library.dll。以下命令检查导出的符号:

    > dumpbin /EXPORTS library.dll
    

    您应该会看到以下内容:

    Dump of file library.dll
    
    File Type: DLL
    
      Section contains the following exports for library.dll
    
        00000000 characteristics
        FFFFFFFF time date stamp
            0.00 version
               1 ordinal base
               1 number of functions
               1 number of names
    
        ordinal hint RVA      name
    
              1    0 00001000 ?func@@YAHH@Z
    

    如您所见,library.dll 导出了一个函数 ?func@@YAHH@Z,这就是 C++ 在内部命名函数 func 的方式。如果您省略 __declspec(dllexport),您将看不到此导出。同样,只有带有 __declspec(dllexport) 注释的类才会导出其所有成员函数。

    总结:要从 DLL 中导出函数,您必须使用 __declspec(dllexport) 对其进行注释。

    现在,从 DLL 导出类的常用方法是在标题中定义这样的 #ifdef 开关:

    // header.h
    #pragma once
    
    #ifdef BUILD_LIBRARY
    #define EXPORT __declspec(dllexport)
    #else
    #define EXPORT __declspec(dllimport)
    #endif
    
    EXPORT int func(int x);
    

    在库的源代码中,您可以定义这个神奇的宏 BUILD_LIBRARY

    // library.cpp
    #define BUILD_LIBRARY
    #include "header.h"
    
    int func(int x) { return 2 * x; }
    

    因此,该函数将从您的库中导出。您的 DLL 的使用者将包括 header.h,但不应定义 BUILD_LIBRARY

    #include "header.h"
    #include <iostream>
    
    int main() {
        std::cout << func(10) << std::endl;
        return 0;
    }
    

    由于这个编译单元没有定义BUILD_LIBRARY,所以EXPORT宏等于__declspec(dllimport)

    【讨论】:

      【解决方案2】:

      宏在你的 sn-p 中定义:

      #ifdef WEBRTC_LIBRARY_IMPL
      #define RTC_EXPORT __declspec(dllexport)  
      #else
      #define RTC_EXPORT __declspec(dllimport)
      #endif
      

      这允许对动态库和调用者代码使用相同的类声明。

      dllexport 和 dllimport 存储类属性是 对 C 和 C++ 语言的特定于 Microsoft 的扩展。您可以使用 它们可以将函数、数据和对象导出或导入 动态链接库。

      https://docs.microsoft.com/en-us/cpp/cpp/dllexport-dllimport?view=vs-2019

      【讨论】:

      • class Myclass {...}; 有什么区别?和类 RTC_EXPORT Myclass {...} ?在类声明中添加宏的目的是什么?
      • 不同的是,不是你“谁有课”,而是别人设计了一个库。这个符号必须从这个库中导出,才能让你使用在你的模块之外定义的东西。每当您设计自己的类并且不打算将其提取到库中时,class MyClass {}; 就足够了。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-07-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-21
      • 2018-05-22
      相关资源
      最近更新 更多