Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I override a class scoped __declspec(dllexport) annotation on a per-member basis?

On ELF targets, if I have class Foo and I have given it default visibility via a declaration like class __attribute__((visibiility("default"))) Foo, I can then selectively exempt certain members of the class from having default visibility by annotating them explicitly with __attribute__((visibility("hidden")). This can be useful for inline methods that should not form part of the ABI, so that if they are emitted when building the library defining class Foo, they are not exported, or for private members or types within class Foo that should also not form part of its ABI.

However, on Windows, there appears to be no means to achieve this. While an unadorned class Foo is automatically private to a DLL, once adorned as class __declspec(dllexport) Foo, the entire class is now dllexport, and there appears to be no associated annotation that can selectively override the __dllexport status of a specific member. Tagging the select "not for export" members as __declspec(dllimport) is clearly wrong.

Is there some other way to prevent the class scoped __dllexport from applying to certain class members and/or types?

To make this more concrete, what I would like to say, and can say, when using ELF annotations is:

class __attribute__((visibility("default"))) Foo {
public:
    Foo(); // OK, default visibility

    // Don't let inlines join the ABI
    __attribute__((visibility("hidden")) inline void something() { ... }

private:
    // Don't let private members join the ABI
    __attribute__((visibility("hidden")) void _internal();

    // Our pImpl type is also not part of the ABI.
    struct __attribute__((visibility("hidden")) pimpl;
};

But I can't form the same thing using the MSVC attributes:

class __declspec(dllexport) Foo {
public:
    Foo(); // OK, dllexport'ed

    // Don't let inlines join the ABI, but how to say it?
    __declspec(???) inline void something() { ... }

private:
    // Don't let private members join the ABI, but how?
    __declspec(???) void _internal();

    // Our pImpl type is also not part of the ABI, but how?
    struct __declspec(???) pimpl;
};

In a real world implementation, I'd expect the variation between these to be hidden behind a macro.

Is there some __declspec that I'm overlooking that has the semantics of __attribute__((visibility("hidden"))) and can override the class scope application of __declspec(dllexport)?

like image 862
acm Avatar asked Mar 14 '17 14:03

acm


People also ask

What does __ Declspec Dllexport do?

The __declspec(dllexport) attribute exports the definition of a symbol through the dynamic symbol table when building DLL libraries.

What does __ Declspec do?

__declspec The extended attribute syntax simplifies and standardizes Microsoft-specific extensions to the C and C++ languages.

What is Dllexport and Dllimport?

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.

How do I export a class in C++?

You can export an entire C++ class by placing the __declspec(dllexport) before the class name, or you can export a single method by placing __declspec(dllexport) before the method name. Make class methods static and public. The C/C++ DLL Adapter does not allow you to call public non-static methods.


1 Answers

MSDN documentation gives an idea of how it can be done. Here's a sample.

DLL_declspec.h:

#if defined(BUILD_DLL)
   #define DLL_DECLSPEC __declspec(dllexport)
#else
   #define DLL_DECLSPEC __declspec(dllimport)
#endif

To export the whole class:

#include "DLL_declspec.h"

class DLL_DECLSPEC TestExport
{
   public:

      TestExport();

      ~TestExport();

      std::string getName();

      int getID();
};

To export only a few handpicked members of the class:

#include "DLL_declspec.h"

class TestExport
{
   public:

      DLL_DECLSPEC TestExport();

      DLL_DECLSPEC ~TestExport();

      DLL_DECLSPEC std::string getName();

      int getID();
};
like image 179
R Sahu Avatar answered Oct 11 '22 11:10

R Sahu