Macro For Dllexport/Dllimport Switch

Macro for dllexport/dllimport switch

Best place to define COMPILING_DLL=1 is command line of compiler. If you use Visual Studio IDE then it is in Project properties ... C/C++ ... Preprocessor ... Preprocessor Definitions.

__declspec(dllimport) is Microsoft specific extension to C++. Microsoft has excellent online documentation.

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.

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.

How can I handle DLL_EXPORT when compiling dll to a static library?

I would just introduce a second (optional) macro, something like ZMQ_STATIC:

#if defined(ZMQ_STATIC)
# define ZMQ_EXPORT
#elif defined(DLL_EXPORT)
# define ZMQ_EXPORT __declspec(dllexport)
#else
# define ZMQ_EXPORT __declspec(dllimport)
#endif

Define said macro both when building your library as a static library or when consuming it as a static library.

what does __declspec(dllexport) do , when add it before a import function

First, think about what you need without the macro. If a class or
function is defined in module1, you need to declare it
__declspec(dllexport) in module1, and __declspec(dllimport) in all
of the other modules. Including in the header file where it is
declared.

Since you don't want to maintain two different header files, and you
don't what conditional compilation all over the place, the best solution
is use a conditionally defined macro, e.g.:

#ifdef MODULE1
#define MODULE1_DECL __declspec(dllexport)
#else
#define MODULE1_DECL __declspec(dllimport)
#endif

When invoking the compiler, you only define MODULE1 in the project
module1; you don't define it in any other project. So when compiling
module1, MODULE1_DECL expands to __declspec(dllexport), and when
compiling any other module, it expands to __declspec(dllimport).

linkage between dllimport and dllexport

From what I understand, you have something like this in module.h:

__declspec(dllexport) void f();

And then, you have a similar statement in your moduleWrapper.cpp:

__declspec(dllimport) void f();

That counts as a function declaration, so you remove any need to include module.h. The way it's commonly done is by putting the following code in your include file:

#ifdef PROJECTNAME_EXPORTS // (the default macro in Visual Studio)
#define PROJECTAPI __declspec(dllexport)
#else
#define PROJECTAPI __declspec(dllimport)
#endif

And then declaring your function in the header file like this:

PROJECTAPI void f();

That way, it will translate to dllexport when you're compiling your DLL, and to dllimport in any files that are not part of your DLL and that happen to be using the header.

__declspec(dllimport) how to load library

This is the compiler/linker job, it's done automatically as long as you

  1. include the .lib in the Linker options
  2. provide the DLL at runtime so that it's found by the exe

The .lib file is generated when you compile the DLL, or is shipped with it if it's not your code. In this case the code is compiled with __declspec(dllexport).

When compiling your exe, the compiler sees that the included function is to be found in DLL. In this case the code is compiled with __declspec(dllimport).

The linker is provided with the .lib file, and generates appropriate instructions in the exe.

These instructions will make the Exe find the DLL and load the exported function at runtime. The DLL just has to be next to the Exe (there are other possible places, however).

Switching between __declspec(dllimport) and __declspec(dllexport) is done by a macro, provided by Visual C++ when creating a DLL project.



Related Topics



Leave a reply



Submit