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

发布于 2024-09-13 12:24:24 字数 1450 浏览 14 评论 0 原文

我正在开发一个 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) 关键字必须出现在 调用约定关键字,如果 指定了关键字。

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

那么 COM DLL 必须使用 def 文件导出其方法吗?


更新1

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

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

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

I am developing a COM dll and trying to export the DllGetClassObject() method with the __declspec(dllexport).

Here is my declaration:

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

But I kept get this error:

error C2375: 'DllGetClassObject' : redefinition; different linkage

So I try to check all the occurrence of the DllGetClassObject definitions. Thus found the following one in the ObjBase.h.

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

the STDAPI turns out to be like this:

#define STDAPI                  EXTERN_C HRESULT STDAPICALLTYPE

in other words, it's like this:

#define STDAPI                  extern "C" HRESULT __stdcall

According to MSDN:

To export functions, the
__declspec(dllexport) keyword must appear to the left of the
calling-convention keyword, if a
keyword is specified.

But my declaration mentioned before just didn't work.

So does COM DLL have to export their methods with a def file?


Update 1

I tested my declaration with a different method name, shown as below:

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

And this method was exported successfully. So these specifiers could be used together. It seems the Visual C++ compiler takes STDAPI and extern "C" HRESULT __declspec(dllexport) __stdcall as not compatible.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

酷炫老祖宗 2024-09-20 12:24:24

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

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

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

请注意,对于 x64 构建,您可能有有条件地编译编译指示,我认为是:

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

This problem occurs I think because a __stdcall function (for 32-bit builds) is normally decorated with a underscore prefix and an @count postfix. But if the function is also marked as __declspec(dllexport) additional decorations are added (__imp, I think).

You might be able to avoid using a .def file with the following pragma, if you're willing to live with the pragma (I think I'd go for the .def file):

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

Note that for an x64 build, you might have to conditionally compile the pragma, which I think would be:

#pragma comment( linker, "/export:DllGetClassObject" )
转身以后 2024-09-20 12:24:24

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

It doesn't compile because the original declaration in objbase.h didn't have the __declspec(dllexport) attribute. You cannot add it in the definition. Won't help anyway, the name decoration isn't appropriate. Michael showed you what to do about that.

梦太阳 2024-09-20 12:24:24

我会勇敢地说“是”。

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

I'm going to go out on a limb and say yes.

Even Visual Studio 2008 automatically generates the .def file for ATL COM .dll projects.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文