为什么我不能使用__declspec(dllexport)从COM DLL导出DllGetClassObject()?

smw*_*dia 9 c++ com name-decoration

我正在开发一个COM DLL并尝试使用__declspec(dllexport)导出DllGetClassObject()方法.

这里是我的报关表:

extern "C" HRESULT __declspec(dllexport) __stdcall DllGetClassObject(REFCLSID rclsid, 
                                                             REFIID riid, void** ppv)
Run Code Online (Sandbox Code Playgroud)

但我一直得到这个错误:

error C2375: 'DllGetClassObject' : redefinition; different linkage
Run Code Online (Sandbox Code Playgroud)

所以我尝试检查所有DllGetClassObject定义的出现.于是在ObjBase.h中找到了以下一个.

STDAPI  DllGetClassObject(__in REFCLSID rclsid, __in REFIID riid, __deref_out LPVOID FAR* ppv);
Run Code Online (Sandbox Code Playgroud)

事实证明,STDAPI是这样的:

#define STDAPI                  EXTERN_C HRESULT STDAPICALLTYPE
Run Code Online (Sandbox Code Playgroud)

换句话说,它是这样的:

#define STDAPI                  extern "C" HRESULT __stdcall
Run Code Online (Sandbox Code Playgroud)

根据MSDN:

要导出函数,如果指定了关键字,__ declspec(dllexport)关键字必须出现在calling-convention关键字的左侧.

但我之前提到的声明没有奏效.

那么COM DLL 必须def文件导出他们的方法吗?


更新1

我用不同的方法名称测试了我的声明,如下所示:

extern "C" HRESULT __declspec(dllexport) __stdcall f()
{
    return S_OK;
}
Run Code Online (Sandbox Code Playgroud)

并且此方法已成功导出.所以这些说明符可以一起使用.似乎Visual C++编译器将STDAPIextern"C"HRESULT __declspec(dllexport)__stdcall视为不兼容.

Mic*_*urr 9

我想这个问题是因为__stdcall函数(对于32位版本)通常用下划线前缀和@count后缀修饰.但如果该功能也被标记为__declspec(dllexport)添加了额外的装饰(__imp我认为).

如果您愿意使用pragma(我想我会选择.def文件),您可以避免使用带有以下编译指示的.def文件:

#pragma comment( linker, "/export:DllGetClassObject=_DllGetClassObject@12" )
Run Code Online (Sandbox Code Playgroud)

请注意,对于x64构建,您可能必须有条件地编译pragma,我认为这将是:

#pragma comment( linker, "/export:DllGetClassObject" )
Run Code Online (Sandbox Code Playgroud)