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)
?
The __declspec(dllexport) attribute exports the definition of a symbol through the dynamic symbol table when building DLL libraries.
__declspec The extended attribute syntax simplifies and standardizes Microsoft-specific extensions to the C and C++ languages.
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.
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.
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();
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With