Как я могу переопределить аннотацию __declspec (dllexport) класса, предназначенную для каждого члена?

В целевых ELF, если у меня есть class Foo, и я дал ему видимость default с помощью объявления типа class __attribute__((visibiility("default"))) Foo, тогда я могу выборочно освободить некоторых членов класса от видимости default, явно аннотируя их с __attribute__((visibility("hidden")). Это может быть полезно для встроенных методов, которые не должны составлять часть ABI, поэтому, если они генерируются при создании библиотеки, определяющей class Foo, они не экспортируются или для private членов или типов внутри class Foo, которые должны также не являются частью его ABI.

Однако, в Windows, похоже, нет средств для достижения этого. В то время как неприкрашенный class Foo автоматически является приватным для DLL, однажды украшенный как class __declspec(dllexport) Foo, весь класс теперь dllexport, и, похоже, нет связанной аннотации, которая может выборочно переопределять статус __dllexport определенного члена, Маркировка элементов "не для экспорта" как __declspec(dllimport) явно неверна.

Есть ли другой способ предотвратить использование класса __dllexport для определенных членов класса и/или типов?

Чтобы сделать это более конкретным, что я хотел бы сказать и могу сказать, при использовании аннотаций ELF:

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;
};

Но я не могу создать одно и то же, используя атрибуты MSVC:

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;
};

В реализации реального мира я ожидаю, что разница между ними будет скрыта за макросом.

Есть ли какой-то __declspec, который я пропускаю, который имеет семантику __attribute__((visibility("hidden"))) и может переопределить приложение scope класса __declspec(dllexport)?

Ответы

Ответ 1

Документация MSDN дает представление о том, как это можно сделать. Здесь образец.

DLL_declspec.h:

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

Чтобы экспортировать весь класс:

#include "DLL_declspec.h"

class DLL_DECLSPEC TestExport
{
   public:

      TestExport();

      ~TestExport();

      std::string getName();

      int getID();
};

Чтобы экспортировать только выбранные элементы класса:

#include "DLL_declspec.h"

class TestExport
{
   public:

      DLL_DECLSPEC TestExport();

      DLL_DECLSPEC ~TestExport();

      DLL_DECLSPEC std::string getName();

      int getID();
};

Ответ 2

Я никогда не делал такого, но после документации MSDN это должно быть возможно.

Вы не должны указывать __declspec на уровне класса и указывать только __declspec(dllexport) для членов, которые вы хотите.

Надеюсь на эту помощь.