I did the dll tutorial from codeguru.com. There are the following lines in the header:
#if defined DLL_EXPORT
#define DECLDIR __declspec(dllexport)
#else
#define DECLDIR __declspec(dllimport)
#endif
But: If I use it as suggested, I get an error during compilation (defined as import). If I exchange dllexport with dllimport and vice versa, it compiles fine and the call from another application works fine. Like this:
#if defined DLL_EXPORT
#define DECLDIR __declspec(dllimport)
#else
#define DECLDIR __declspec(dllexport)
#endif
Is this an error in the tutorial, or am I missing something?
I use mingw and the gcc-compiler. As some might notice, I asked something similar in the comments there.
In the article, you linked, in the listing of the first .cpp file, at line 4 is:
#define DLL_EXPORT
This will insure that when this DLL is compiled, it will include this symbol defined and thus use:
#define DECLDIR __declspec(dllexport)
In the header file, which will also be included by client projects, there is no such definiation, and thus will use:
#define DECLDIR __declspec(dllimport)
This is the correct usage.
Related
I've created a DLL a file, and in the header file I see :
#ifdef WIN32DLL_EXPORTS
I don't understand what does it mean and where/how we can set up WIN32DLL_EXPORTS.
if I use:
#ifdef WIN32DLL_EXPORTS
#define WIN32DLL_API __declspec(dllexport)
#else
#define WIN32DLL_API __declspec(dllimport)
#endif
WIN32DLL_API int testSum(void);
testSum is considered as __declspec(dllimport). So I think my project is not set to WIN32DLL_EXPORTS? How can I change this?
There is a comment block immediately above the line you quoted. Read it.
// The following ifdef block is the standard way of creating macros which make exporting
// from a DLL simpler. All files within this DLL are compiled with the WIN32DLL_EXPORTS
// symbol defined on the command line. this symbol should not be defined on any project
// that uses this DLL. This way any other project whose source files include this file see
// WIN32DLL_API functions as being imported from a DLL, wheras this DLL sees symbols
// defined with this macro as being exported.
#ifdef WIN32DLL_EXPORTS
#define WIN32DLL_API __declspec(dllexport)
#else
#define WIN32DLL_API __declspec(dllimport)
#endif
You can either:
define WIN32DLL_EXPORTS in the project's Properties > Configuration Properties > C/C++ > Preprocessor > Preprocessor definitions.
if you use a precompiled header (e.g. stdafx.h) then you can also define WIN32DLL_EXPORTS
there with a #define statement.
I'm trying to figure a "clean way" of using the default preprocessor definitions to determine what parts of my code should be compiled based on the platform and compiler.
My current test setup involves a Windows machine with Visual C++ compiler and a Debian with g++ compiler.
Currently I have something like this:
#if defined (__GNUG__)
#define ASMMath_EI __attribute__ ((__visibility__("default")))
#elif defined (WIN32)
#ifdef ASMMath_EXPORTS
#define ASMMath_EI __declspec(dllexport)
#else
#define ASMMath_EI __declspec(dllimport)
#endif
#endif
extern void ASMMath_EI AsmProblemOne();
And it works, but I figure there might and must be some better definitions I can check for. Or perhaps some more ideal way with CMake?
Suggestions?
There is a nice listing of Compiler, Operating System, and Architecture preprocessor names at those links. You could branch for the systems and compilers you care about supporting/detecting. Additionally a lot of this work is already done in boost/config/ (see boost/config/select_compiler_config.hpp as one example for compiler flags) using Boost headers. Not everyone likes including Boost, which is why the first set of links is generic from library specific support.
Answered by the OP in a question edit:
From what I gather the following would be ideal way to implement this:
// MasterHeader.h
#if defined _MSC_VER // Defined by visual studio
#define PROJ_TMP_DLL_IMPORT __declspec(dllimport)
#define PROJ_TMP_DLL_EXPORT __declspec(dllexport)
#else
#if __GNUC__ >= 4 // Defined by GNU C Compiler. Also for C++
#define PROJ_TMP_DLL_IMPORT __attribute__ ((visibility ("default")))
#define PROJ_TMP_DLL_EXPORT __attribute__ ((visibility ("default")))
#else
#define PROJ_TMP_DLL_IMPORT
#define PROJ_TMP_DLL_EXPORT
#endif
#endif
#ifdef PROJ_EXPORTS
#define PROJ_API PROJ_TMP_DLL_EXPORT
#else
#define PROJ_API PROJ_TMP_DLL_IMPORT
#endif
-
// File.h
#include "MasterHeader.h"
extern void PROJ_API SomeFunction();
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Windows & C++: extern & __declspec(dllimport)
Why/when is __declspec( dllimport ) not needed?
I want to write a DLL project. This project include several DLLs. They are dependent. I define some macros like follow :
#ifdef MYDLL_DECL1
#define DLL_DECL __declspec(dllexport)
#else
#define DLL_DECL __declspec(dllimport)
#endif
I defined MYDLL_DECL1...MYDLL_DECLn for each modules. Because I thought if i define the same macro that it wouldn't work . But I really want to define only one macro, and i wrote a testbed. I have two modules. In the second moudle's source file. I write code like follow:
#define MYDLL_DECL
#include "moudle1.h"
#include "moudle2.h"
If I use the same macro name "MYDLL_DECL" ,for modle1's head file I have defined "MYDLL_DECL", so "DLL_DECL" is equal to '__declspec(dllexport)'. Actually in module2 it should be equal to "__declspec(dllimport)", Because module2 import module1. But I found it worked when I just define a same macro for two module. And I also find that the OpenCV also use this methold to its library
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).
What is the specification of CC_DLL in this line"class CC_DLL CCSize" in Cocos2d-x.
Every Class in cocos2d-x Define like that --> class ..... classname
It create confusion for me. Plz help me out.
Thanks,
It's probably a preprocessor definition telling the module to either export or import the class.
Something like:
#ifdef BUILDING_COCOS
#define CC_DLL _declspec(dllexport)
#else
#define CC_DLL _declspec(dllimport)
#endif
When linking against the library, BUILDING_COCOS is not defined, so CC_DLL will mean _declspec(dllimport), which tells the compiler that the class is exported in a binary.
I assume CC_DLL to be defined something like this (using MSVC intrinsics syntax):
#ifdef CC_IS_IMPLEMENTATION /* or CC_IS_DLL_COMPILATION or something like that */
#define CC_DLL __declspec(dllexport)
#else
#define CC_DLL __declspec(dllimport)
#endif
This is done to have a single definition that either exports or imports the class to/from a dll, based on whether the API is used by a user or by the implementation itself. The implementation (.cpp file) would then look something like this:
// .cpp file
#define CC_IS_IMPLEMENTATION
// CC_DLL is now defined to __declspec(dllexport)
#include "myapi_stuff.h"
// implement it...
And if a library / dll user uses that API (class), it is defined as __declspec(dllimport) to import the implementation from a dll.
In my C++ header file, I have the following:
#ifdef _DLL
#define DLL_API __declspec(dllexport) // Being compiled as a DLL.
#else
#define DLL_API // Not being compiled as a DLL.
#endif
Later on, I have things like:
DLL_API int GetNumber();
I'm oversimplifying, but the basic question here is whether there's a way to get the compiler to just skip over DLL_API if it's not defined.
No.
When DLL_API is defined as preprocessor macro that contains nothing then preprocessor replaces DLL_API with nothing and compiler will see nothing there. If it is undefined for preprocessor then preprocessor does nothing with it. Then compiler will see it unchanged and you get compiler error about unknown identifier DLL_API, because such thing is not part of C++ language.
Attributes like __declspec() are platform specific extensions and it is common convention to wrap their usage in interfaces into preprocessor macros.
Usually, it is
#ifdef _WIN32
#ifdef _DLL
#define DLL_API __declspec(dllexport) // Being compiled as a DLL.
#else
#define DLL_API __declspec(dllimport) // Not being compiled as a DLL.
#endif
#else
#define DLL_API
#endif
so that it is portable, and DLL_API is always transformed into something valid.