extern "C" с классом и DLL - PullRequest
       15

extern "C" с классом и DLL

0 голосов
/ 10 сентября 2018

Мне был представлен исходный код C ++ DLL, который использует extern "C":

extern "C"
{
    class Something
    {
       public:
         __declspec(dllexport) Something();
         __declspec(dllexport) virtual ~Something();
         __declspec(dllexport) bool function_one(const char * some_text);
         static __declspec(dllexport) char * get_version();
       private:
          unsigned int m_data;
    };
}

DLL вызывается программой на C ++. К вашему сведению, используя Visual Studio 2017 на платформе Windows 7.

Вопросы * (все относящиеся к extern "C" и class):

  1. Поскольку class не является языком C, это будет эквивалентно struct
  2. Допустимы ли конструкторы?
  3. Действительны ли виртуальные деструкторы (поскольку C не имеет virtual)?
  4. Как обрабатывается bool?
  5. Как static обрабатывается внутри extern "C" для класса?
  6. Как обрабатываются данные private внутри блока extern "C"?
  7. Как обрабатывается noexcept в блоке extern "C" для конструктор?

Компилятор Visual Studio 2017 не генерирует никаких ошибок или предупреждений с помощью приведенного выше кода.

Анализатор кода VS2017 генерирует только предупреждение для конструктора:

C26439 This kind of function may not throw. Declare it 'noexcept' (f.6).

Исследование:
В вопросах StackOverflow, связанных с этой проблемой, упоминается, что "extern" C "has the effect of resolving name mangling. However, they don't address the issues of virtual , bool`, личные данные и т. Д., Как я перечислил выше.

Кроме того, во многих ответах, связанных с DLL, рекомендуется не использовать структуры, отличные от POD, поскольку компоновка может меняться в разных компиляторах (включая одни и те же версии компиляторов); так, например, символьные массивы предпочтительнее, чем std::string.

1 Ответ

0 голосов
/ 10 сентября 2018

Это не меняет код на C. Это не приводит к искажению имен в C ++, поэтому вы не можете перегрузить функции, выставленные, например, как extern "C" внутри этого блока, но код все еще C ++.

Вам запрещено делать вещи, которые не могут быть вызваны из C (в блоке extern "C"). Вы представляете C API, но вы все еще можете использовать C ++ за кулисами. Только не в вашей extern "C" части интерфейса .

Это также означает, что вы не можете экспортировать функции-члены (virtual или нет) как extern "C", потому что C не имеет такой вещи.

...