What Is _Declspec and When Do I Need to Use It

What is __declspec and when do I need to use it?

This is a Microsoft specific extension to the C++ language which allows you to attribute a type or function with storage class information.

Documentation

__declspec (C++)

what does __declspec(dllimport) really mean?

__declspec is a Microsoft-specific attribute that allows you to specify storage-class information.

(Nitpicker's Corner: However, a number of other compiler vendors—e.g. GCC—now support this language extension for compatibility with the installed base of code that was written targeting Microsoft's compilers. Some even provide additional storage-class attributes.)

Two of those storage-class attributes that can be specified are dllimport and dllexport. These indicate to the compiler that a function or object is imported or exported (respectively) from a DLL.

More specifically, they define the DLL's interface to the client without requiring a module-definition (.DEF) file. Most people find it much easier to use these language extensions than to create DEF files.

For obvious reasons, __declspec(dllimport) and __declspec(dllexport) are generally paired with one another. You use dllexport to mark a symbol as exported from a DLL, and you use dllimport to import that exported symbol in another file.

Because of this, and because the same header file is generally used both when compiling the DLL and in client code that consumes the DLL's interface, it is a common pattern to define a macro that automatically resolves to the appropriate attribute specifier at compile-time. For example:

#if COMPILING_DLL
#define DLLEXPORT __declspec(dllexport)
#else
#define DLLEXPORT __declspec(dllimport)
#endif

And then marking all of the symbols that should be exported with DLLEXPORT.

Presumably, that is what the Q_CORE_EXPORT macro does, resolving to either Q_DECL_IMPORT or Q_DECL_EXPORT.

__declspec(dllexport) and __declspec(dllimport) in C++

The Windows-exclusive __declspec(dllexport) is used when you need to call a function from a Dll (by exporting it) , that can be accessed from an application.

Example This is a dll called "fun.dll" :


// Dll.h :

#include <windows.h>

extern "C" {

__declspec(dllexport) int fun(int a); // Function "fun" is the function that will be exported

}

// Dll.cpp :

#include "Dll.h"

int fun(int a){
return a + 1;
}

You can now access the "fun" from "fun.dll" from any application :

#include <windows.h>

typedef int (fun)(int a); // Defining function pointer type

int call_fun(int a){
int result = 0;

HMODULE fundll = LoadLibrary("fun.dll"); // Calling into the dll

if(fundll){
fun* call_fun = (fun*) GetProcAddress(fundll, "fun"); // Getting exported function
if(call_fun){
result = call_fun(a); // Calling the exported fun with function pointer
}
}
return result;
}

Why/when is __declspec( dllimport ) not needed?

__declspec(dllimport) is a client-side MSVC attribute that can be specified for imported code and data.

It isn't required for code. It is an optimization; a client-side compiler hint that a function call isn't direct but imported. The imported function pointer for a function named foo() will be __imp_foo. Without the hint, a thunk is created to load the address in __imp_foo and jump to it. With the hint the thunk is skipped and an indirect call through the IAT1 entry is generated i.e. the thunk is inlined. It is a time optimization, not space.

It's required for data that's imported from a DLL.

This blog post has the details.

1: Import Address Table of a program

Why do we use __declspec(dllimport) when it seems so useless?

From the documentation:

Using __declspec(dllimport) is optional on function declarations, but the compiler produces more efficient code if you use this keyword. However, you must use __declspec(dllimport) for the importing executable to access the DLL's public data symbols and objects. Note that the users of your DLL still need to link with an import library.

Using __declspec( dllexport )

When compiling the DLL you have to write __declspec(dllexport) as you did. This tells the compiler you want it to be exported. When using the DLL you want __declspec(dllimport) in your included files. The compiler then knows that this functions and classes are in a DLL-file and need to be imported. Because you don't want to change your header-files that much, you should define a macro e.g. BUILD_DLL.

    #ifdef BUILD_DLL
#define DLL_PORTING __declspec(dllexport)
#else
#define DLL_PORTING __declspec(dllimport)
#endif

Now you write in example.h:

    class DLL_PORTING example_class { … };

In your .exe file just include the header files you need and everything will work.



Related Topics



Leave a reply



Submit