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.
Related
I am reading a C++ header file, in which there writes:
class CLASSEXPORT skExecutable : {.....}
A comment says that CLASSEXPORT is a macro expansion and then I find where CLASSEXPORT is defined.
#define CLASSEXPORT
And that's all..I feel confused about this..What does CLASSEXPORT represent in this sense? And how to understand the class skExecutable?
In your case, CLASSEXPORT is expanded to nothing (probably because it is not needed to expand it into something meaningful in your exact configuration), so your class will just be a class skExecutable {<...>};. This approach is commonly used for import/export directives, e.g. in the following snippet an appropriate directive will be places depending on whether COMPILING_DLL macro is defined:
#if COMPILING_DLL
#define DLLEXPORT __declspec(dllexport)
#else
#define DLLEXPORT __declspec(dllimport)
#endif
class DLLEXPORT MyClass
{
};
Just to clear some stuff up: CLASSEXPORT is a macro. Macro expansion is a process, performed prior to compilation, during which all macros are replaced with whatever they are defined as.
In your case, I suspect that CLASSEXPORT is there to allow all classes that are declared in that way to be exported to some kind of shared library if the need arises in the future. Then that CLASSEXPORT would be defined as something like
#define CLASSEXPORT __declspec(dllexport)
and you could use skExecutable directly from a shared library.
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).
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)
I'm trying to understand some C++ code which has the following class syntax:
class Q_MONKEY_EXPORT BasePlugin : public QObject
{
// some code comes here
};
I cannot understand the syntax class Q_MONKEY_EXPORT BasePlugin. To me it looks like if there are two names for the class. What exactly does this kind of syntax mean in C++?
Q_MONKEY_EXPORT is most likely a #define somewhere. Defines like that are sometimes required, for example when the class is in a library and needs to be exported when the header file is included from somewhere else. In that case, the define resolves to something like __declspec(dllexport) (the exact syntax will depend on the tools you are using).
That's most probably a preprocessor directive telling the compiler the symbol is to be exported.
It's probably defined as:
#define Q_MONKEY_EXPORT _declspec(dllexport)
which will cause your class to be exported to the dll.
The full declaration will be expanded, before compilation, to:
class _declspec(dllimport) BasePlugin : public QObject
{
// some code comes here
};
EDIT:
As David Heffernan pointed out, macros like these are generally used to let the compiler know whether it needs to import or export the symbols. Usually defined as dllimport for outside modules and dllexport when building the module. I doubt that's the case here, since the name suggests exporting, but it's best to check the documentation or actually go to the definition.
Q_MONKEY_EXPORT is a macro (all upper case is convention for macro) that typically resolves to something like __declspec(dllexport) when you are building the DLL and resolves to __declspec(dllimport) when you are using the DLL.
You can find out exactly what it is by reading your include files.
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