Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't I use __declspec(dllexport) to export DllGetClassObject() from a COM DLL?

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.

like image 504
smwikipedia Avatar asked Aug 11 '10 16:08

smwikipedia


People also ask

What does __ Declspec Dllexport do?

__declspec(dllexport) adds the export directive to the object file so you do not need to use a . def file. This convenience is most apparent when trying to export decorated C++ function names.

What does __ Declspec do?

__declspec attributes The __declspec keyword enables you to specify special attributes of objects and functions. For example, you can use the __declspec keyword to declare imported or exported functions and variables, or to declare Thread Local Storage (TLS) objects.

How do I export a function in C++?

Use __declspec(dllexport) to export the function or method. You can export an entire C++ class by placing the __declspec(dllexport) before the class name, or you can export a single method by placing __declspec(dllexport) before the method name.


2 Answers

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" )
like image 99
Michael Burr Avatar answered Oct 14 '22 02:10

Michael Burr


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.

like image 21
Hans Passant Avatar answered Oct 14 '22 00:10

Hans Passant