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.
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.
__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.
__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.
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.
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" )
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With