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

时间:2010-08-11 16:19:51

标签: c++ com name-decoration

我正在开发一个COM dll并尝试使用 __ declspec(dllexport)导出DllGetClassObject()方法。

这是我的声明:

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
换句话说,就像这样:

#define STDAPI                  extern "C" HRESULT __stdcall

根据MSDN

  

要导出功能,   __declspec(dllexport)关键字必须出现在左侧   calling-convention关键字,如果是   指定了关键字。

但我之前提到的声明不起作用。

COM DLL 是否必须使用 def 文件导出其方法?


更新1

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

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

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

3 个答案:

答案 0 :(得分:9)

我认为会出现此问题,因为__stdcall函数(对于32位版本)通常使用下划线前缀和@count后缀进行修饰。但是如果该函数也标记为__declspec(dllexport),我会添加其他装饰(__imp)。

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

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

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

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

答案 1 :(得分:3)

它不能编译,因为objbase.h中的原始声明没有__declspec(dllexport)属性。您无法在定义中添加它。无论如何都不会帮助,装饰名称不合适。迈克尔告诉你该怎么做。

答案 2 :(得分:0)

我要走出去,说是的。

甚至Visual Studio 2008也会自动为ATL COM .dll项目生成.def文件。