Mukesh Kumar
Mukesh Kumar

Reputation: 322

class declaration in C++

I have a Class : class RTC_EXPORT PeerConnectionInterface : public rtc::RefCountInterface { ... };

RTC_EXPORT is defined as

#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_

What does RTC_EXPORT in class RTC_EXPORT PeerConnectionInterface :public rtc::RefCountInterface {...}; do?

Usually we define classes in c++ as class Myclass{...}. What does the additional MACRO do in general?

Upvotes: 0

Views: 294

Answers (2)

phlipsy
phlipsy

Reputation: 2949

In addition to the Dmitry's answer I want to add some practical tools to examine the influence of __declspec(). Consider the following source file:

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

Start a native tools command prompt from your Visual Studio installation inside your start menu. There you can compile and link library.cpp to a DLL with the following commands:

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

There should be a freshly created library.dll next to library.cpp. The following command examines the exported symbols:

> dumpbin /EXPORTS library.dll

You should see something along the following lines:

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

As you can see, library.dll exports a function ?func@@YAHH@Z, that's the way C++ names the function func internally. If you omit __declspec(dllexport), you won't see this export. Likewise, only a class annotated with __declspec(dllexport) will export all of its member functions.

Summary: In order to export a function from a DLL you have to annotate it with __declspec(dllexport).

Now, the usual approach for exporting classes from a DLL is to define such a #ifdef switch in your header:

// header.h
#pragma once

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

EXPORT int func(int x);

Inside the sources of the library you define this magic macro BUILD_LIBRARY:

// library.cpp
#define BUILD_LIBRARY
#include "header.h"

int func(int x) { return 2 * x; }

Thus the function will be exported from your library. Consumers of your DLL will include header.h but shall not define BUILD_LIBRARY:

#include "header.h"
#include <iostream>

int main() {
    std::cout << func(10) << std::endl;
    return 0;
}

Since this compilation unit doesn't define BUILD_LIBRARY the EXPORT macro equals to __declspec(dllimport).

Upvotes: 1

Dmitry Kuzminov
Dmitry Kuzminov

Reputation: 6594

The macros is defined in your snippet:

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

That allows to use the same class declaration for both dynamic library and the caller code.

The dllexport and dllimport storage-class attributes are Microsoft-specific extensions to the C and C++ languages. You can use them to export and import functions, data, and objects to or from a DLL.

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

Upvotes: 0

Related Questions