Почему я не могу использовать declspec(dllexport) для экспорта DllGetClassObject() из COM-библиотеки DLL?

Я разрабатываю com dll и пытаюсь экспортировать метод DllGetClassObject () с помощью _ _ declspec (dllexport).

вот мое заявление:

extern "C" HRESULT __declspec(dllexport) __stdcall DllGetClassObject(REFCLSID rclsid, 
                                                             REFIID riid, void** ppv)

но я продолжал получать эту ошибку:

error C2375: 'DllGetClassObject' : redefinition; different linkage

поэтому я пытаюсь проверить все вхождение определений DllGetClassObject. Таким образом, в ObjBase.h.

STDAPI  DllGetClassObject(__in REFCLSID rclsid, __in REFIID riid, __deref_out LPVOID FAR* ppv);

STDAPI оказывается таким:

#define STDAPI                  EXTERN_C HRESULT STDAPICALLTYPE

in другими словами, это так:

#define STDAPI                  extern "C" HRESULT __stdcall

по данным MSDN:

для экспорта функций _Ключевое слово _declspec(dllexport) должно отображаться слева от ключевое слово calling-convention, если a указывается ключевое слово.

но моя декларация, упомянутая ранее, просто не сработала.

так делает COM DLL обязательно экспортировать свои методы с def файл?


обновление 1

Я проверил свою декларацию с другим именем метода, показанным ниже:

extern "C" HRESULT __declspec(dllexport) __stdcall f()
{
    return S_OK;
}

и этот метод был успешно экспортирован. Таким образом, эти спецификаторы могут использоваться вместе. Кажется, компилятор Visual C++ принимает STDAPI и extern " C " HRESULT _ _ declspec (dllexport) __stdcall как не совместимы.

3 ответов


эта проблема возникает, я думаю, потому что функция __stdcall (для 32-разрядных сборок) обычно украшена префиксом подчеркивания и @count постфикс. Но если функция помечена как __declspec(dllexport) добавлены дополнительные украшения (__imp, Я думаю).

возможно, вы сможете избежать использования a .def файл со следующей прагмой, если вы готовы жить с прагмой (я думаю, что я бы пошел на это .def file):

#pragma comment( linker, "/export:DllGetClassObject=_DllGetClassObject@12" )

обратите внимание, что для сборки x64 у вас может быть чтобы условно скомпилировать прагму, которая, я думаю, будет:

#pragma comment( linker, "/export:DllGetClassObject" )

Он не компилируется, потому что исходное объявление в objbase.H не имел атрибута __declspec(dllexport). Вы не можете добавить его в определении. В любом случае, название не подходит. Майкл показал тебе, что с этим делать.


Я собираюсь пойти на риск и сказать "да".

даже Visual Studio 2008 автоматически создает .def файл для ATL COM .проект DLL.