tags:

views:

78

answers:

3

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.

A: 

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.

MSN
Thanks for your reply. If so, we could share that limb...
smwikipedia
+1  A: 

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" )
Michael Burr
That's it~ Thanks Michael. :)
smwikipedia
+1  A: 

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.

Hans Passant
Thanks Hans. I really appreciate your answers to my questions. Not just this one. :)
smwikipedia