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

I have seen instances of __declspec in the code that I am reading. What is it? And when would I need to use this construct?

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++)

The canonical examples are __declspec(dllimport) and __declspec(dllexport), which instruct the linker to import and export (respectively) a symbol from or to a DLL.
// header
__declspec(dllimport) void foo();
// code - this calls foo() somewhere in a DLL
foo();
(__declspec(..) just wraps up Microsoft's specific stuff - to achieve compatibility, one would usually wrap it away with macros)

It is mostly used for importing symbols from / exporting symbols to a shared library (DLL). Both Visual C++ and GCC compilers support __declspec(dllimport) and __declspec(dllexport). Other uses (some Microsoft-only) are documented in the MSDN.

Another example to illustrate the __declspec keyword:
When you are writing a Windows Kernel Driver, sometimes you want to write your own prolog/epilog code sequences using inline assembler code, so you could declare your function with the naked attribute.
__declspec( naked ) int func( formal_parameters ) {}
Or
#define Naked __declspec( naked )
Naked int func( formal_parameters ) {}
Please refer to naked (C++)

Essentially, it's the way Microsoft introduces its C++ extensions so that they won't conflict with future extensions of standard C++. With __declspec, you can attribute a function or class; the exact meaning varies depending on the nature of __declspec. __declspec(naked), for example, suppresses prolog/epilog generation (for interrupt handlers, embeddable code, etc), __declspec(thread) makes a variable thread-local, and so on.
The full list of __declspec attributes is available on MSDN, and varies by compiler version and platform.

I know it's been eight years but I wanted to share this piece of code found in MRuby that shows how __declspec() can bee used at the same level as the export keyword.
/** Declare a public MRuby API function. */
#if defined(MRB_BUILD_AS_DLL)
#if defined(MRB_CORE) || defined(MRB_LIB)
# define MRB_API __declspec(dllexport)
#else
# define MRB_API __declspec(dllimport)
#endif
#else
# define MRB_API extern
#endif

Related

'#define AP_MODULE_DECLARE(type) type' in C/C++

Why does the apache source have:
#define AP_MODULE_DECLARE(type) type
What is the advantage of using, for example, this form:
AP_CORE_DECLARE(void) ap_add_per_dir_conf(server_rec *s, void *dir_config);`
vs
void ap_add_per_dir_conf(server_rec *s, void *dir_config);
Thanks.
Note that other definitions are possible for those macros. include/ap_config.h has the following (with some indentation added by me):
#if !defined(WIN32) || defined(AP_MODULE_DECLARE_STATIC)
...
# if defined(WIN32)
# define AP_MODULE_DECLARE(type) type __stdcall
# else
# define AP_MODULE_DECLARE(type) type
# endif
...
#else
...
# define AP_MODULE_DECLARE(type) __declspec(dllexport) type __stdcall
...
#endif
Here, AP_MODULE_DECLARE is used to add __stdcall (which specifies a particular calling convention) and/or __declspec(dllexport) (which is related to exporting the function as part of the interface of a shared library).
Note that e.g. the __declspec(dllexport) won't be added if AP_MODULE_DECLARE_STATIC is defined. My guess (which might not be entirely accurate as I'm not familiar with this code) is that it's related to linking a module as a static library, in which case __declspec(dllexport) wouldn't make sense.
If you're wondering what "dso" stands for in the comments in that file, it's for dynamic shared object. It's basically a shared library, though Apache seems to reserve the term shared library for things that aren't loaded at runtime using dlopen(3).

Use case of dllimport in VisualStudio

I always wondered what is the real use case of __declspec(dllimport). I know that building a shared library requires to export its symbols using __declspec(dllexport) and then the user of the library use theses symbols as __declspec(dllimport).
Then, you should build your shared library with a special define which enables dllexport and if the flag is not set, the symbols are defined as dllimport.
However, I never used dllimport at all and it just works.
I have two projects:
ImportExport
Has a small Util class which is build with EXPORTING defined
Util.h:
#ifndef _UTIL_H_
#define _UTIL_H_
#if defined(EXPORTING)
# define EXPORT __declspec(dllexport)
#else
# define EXPORT // I should use __declspec(dllimport) but client will try out
#endif
class EXPORT Util {
public:
static void test();
};
#endif // !_UTIL_H_
Then in the source file Util.cpp:
#include <iostream>
#include "Util.h"
void Util::test()
{
std::cout << "Testing..." << std::endl;
}
Nothing much complicated, as you can see, when the user will use this file, EXPORT will not be defined at all (where it should be defined to dllimport).
The client exe
Main.cpp:
#include <Util.h>
int main(void)
{
Util::test();
return 0;
}
Links to ImportExport.lib without any define set, just works. No undefined reference.
I wonder why is the use case of dllimport? Is it present for backward compatibility?
Note: All the code presented was tested on VisualStudio 2012 Express.
Raymond Chen describes the dll import mechanism in detail in this series; summing it up, dllimport for functions is essentially a performance optimization.
If you don't mark a function as dllimport the compiler and the linker will treat it as a normal function, with "static" function calls resolving it to the stub found in the import library. The stub actually has to fetch the address of the imported function from the IAT and perform a jmp there (i.e. it has to somehow convert the direct call that the compiler generated to an indirect call), so there's some performance penalty in this two-step process.
dllimport, instead, tells the compiler that it has to generate code for an indirect call via the IAT right from the compilation phase. This reduces the indirections and allows the compiler to cache (locally to the function) the target function address.
Notice that, as MSDN says, you can omit dllimport only for functions; for data it's always necessary, because there's not a mechanism available for the linker to rework the direct accesses to variables generated by the compiler in indirect ones.
(all this was particularly relevant in times of "classical" linkers; nowadays, with link-time code generation enabled, all these points can be worked around by simply letting the linker fully generate the function calls/data accesses)

C++ Builder exporting cdecl for cross platform use

I have a library (dll) originally written in MSVS that I need to make cross platform (Mac/Win). I started using XCode but with the new Embarcadero C++ builder XE3 I am thinking that one development environment would be a better way to go.
The host application is written in Delphi so more reason to move it to one set of tools.
For my existing code everything is cdecl but I cannot get this to work on C++ builder. If I convert it to stdcall then it works fine but as I understand it I need to use cdecl when using the library under OSX.
In MSVC I export my functions like this:
extern "C" __declspec(dllexport) int Init(char * init_dir, DebugCallbackFunc f, DeviceCallbackFunc f1)
In C++ Builder I am exporting like this:
extern "C" __declspec( dllexport ) int _cdecl Init(char * init_dir, DebugCallbackFunc f, DeviceCallbackFunc f1)
The problem is that the Delphi host application always returns NULL with GetProcAddress when I use cdecl but works fine if I change it to stdcall.
TUDMXInit = function(p: PAnsiChar; f: TDebugCallbackFunc; f1: TDeviceCallbackFunc): integer; cdecl;
I would also appreciate an example of the best way to handle the '_' that is suppose to prefix the exported function under OSX. Should I just use conditionals to add this at the front of all functions?
Thanks in advance.
Martin
The usual way of doing this is to use macros. declspec and cdecl/stdcall are Windows specific.
The call in OSX(and other Unix) you want is
extern "C" int Init(char * init_dir, DebugCallbackFunc f, DeviceCallbackFunc f1)
So the usual way is to define a macro e.g. DLL_EXPORT see the Boost libraries for examples
e.g. from Serialisation or a simpler description from Tcl
Assuming WINDOWS is defined in your build for Windows libraries
#ifdef WINDOWS
#define DLLEXPORT __declspec( dllexport )
#else
#define DLLEXPORT
#endif
Also you can make this define behave correctly for when building the DLL as here or calling the DLL when you need __declspec( dllimport )
The way I handle such differences is always the same basic idea: look at how each compiler does it, and come up with a macro or a set of macros that can generate all the required forms without being too cumbersome to use.
For your _cdecl, a simple macro like "EXPORT_CDECL" would seem to suffice; you can then set this to expand to nothing, "_cdecl", or "stdcall" as required by the compiler.
You can also use something like this to add something to names, such as #define EXPORT_NAME(Name) _##Name
You can, of course, also make a "big" macro that takes the individual components (return type, function name, function parameters) and spits out the entire result-line.

Strange multiple class names in Linderdaum Engine

I am trying to use Linderdaum Engine and found there many strange declarations like:
class scriptfinal netexportable ClassName: public iObject
These strange names scriptfinal and netexportable are macros. But they are defined to be empty.
Why someone can need this kind of defines?
They're empty so that the C++ compiler won't care about them.
The Linderdaum Engine preprocesses the C++ sources in order to generate meta-information about the classes.
Those macros are most likely used by their preprocessor to generate information for their scripting language (scriptfinal) and .NET serialization code (netexportable).
For example, someone might set the scriptfinal macro to:
#define scriptfinal __declspec(dllimport)
to get:
class __declspec(dllimport) ClassName: public iObject {};
Since __declspec is a Microsoft specific extension so normally it is used by macro expansion in portable code. When compiling for the Linux environment the macros are empty so __declspec is not visible to the compiler and under Windows they will be defined as above.

Macro variable after class keyword

I found this in Ogre Framework
class _OgreSampleClassExport Sample_Character : public SdkSample {
...
...
and it's define like this
#define _OgreSampleClassExport
Why we want to have this macro variable?
Presumably so a special qualifier, such as __declspec(dllexport), could be added to such classes by modifying (or conditionally defining) the define:
#define _OgreSampleClassExport __declspec(dllexport)
It's to allow for future exports. Ogre may just strictly be a statically linked library at the moment, but if the authors ever decide to support dynamically-linked libraries (aka shared libraries on some platforms), they will need to write code like:
class
#ifdef EXPORTING
__declspec(dllexport)
#else
__declspec(dllimport)
#endif
Sample_Character [...]
... and that's just for MSVC. Normally they'd have to go through the effort to do this to Sample_Character and all other classes they provide through their library. Making a single macro to be defined later is much easier as they'll only need to do this in one place.