I have a common utility class that is shared between two projects, an desktop application project and a library project (dll). I'm working under VS2013.
To make this class available to external calls when it's compiled as part of my library, I use a macro like this:
#include "global.h"
class MYCLASS_EXPORT UtilityClass {
public:
...
My global.h file contains the following:
#ifdef MYCLASS_LIBRARY
# define MYCLASS_EXPORT __declspec(dllexport)
#else
# define MYCLASS_EXPORT __declspec(dllimport)
#endif
So when I use that class inside my library I set the preprocessor macro MYCLASS_LIBRARY and an application that link my library can use the UtilityClass.
Instead, when I use that class as part of my C++ desktop application project (that doesn't have the preprocessor macro MYCLASS_LIBRARY), I get from the compiler an "inconsistent dll linkage" error because of MYCLASS_EXPORT declaration.
So, how to declare my class so that can be used both in a library project and in a desktop application project (so without the need to export that class)?
Just to be more clear, a working solution I've found is the following:
#ifdef MYCLASS_LIBRARY
#include "global.h"
#endif
#ifdef MYCLASS_LIBRARY
class MYCLASS_EXPORT UtilityClass {
#else
class UtilityClass {
#endif
public:
...
Now everything compile and run fine, but does not seem a good approach...
I can think of the following option:
In the desktop application, define a macro, MYCLASS_STATIC and change the .h file to use:
#ifdef MYCLASS_STATIC
# define MYCLASS_EXPORT
#elif defined(MYCLASS_LIBRARY)
# define MYCLASS_EXPORT __declspec(dllexport)
#else
# define MYCLASS_EXPORT __declspec(dllimport)
#endif
Related
I'm looking through the source of a library and many classes are defined using the following form
class THING_API ClassName
{
...
Jumping to the macro definition . . .
#ifndef THING_API
#define THING_API /**< This macro is added to all public class declarations. */
#endif
What could this be for, and is it a common technique?
It looks to me very much like export macro, which is required when building a shared library (.dll) on Windows. When compiling with MSVC, You have to put __declspec(export) in that spot when building a library, and __declspec(import) when building its client. This is achieved like so:
#if COMPILING_DLL
#define THING_API __declspec(dllexport)
#else
#define THING_API __declspec(dllimport)
#endif
Then you define COMPILING_DLL for the library project, and leave it undefined for all other projects. And if you're not on Windows or compiling a static library, you need to define it blank like it's done in your question.
P. S. Other Windows compilers use their own keywords instead of __declspec(dllimport), but the principle remains.
One possible use would be to allow you to conditionally mark the class as callable from other libraries in a cross-platform library.
class ClassName
would be callable on Windows using MSVC but you'd need
class __attribute__ ((visibility("default"))) ClassName
for linux using gcc.
In this case, THING_API might be defined like
#ifdef _WIN32
# define THING_API
#else
# define THING_API __attribute__ ((visibility("default")))
#endif
Empty macros like that are often used so that other parsers can gather information from the headers.
Apple has the empty IBOutlet macro which the Interface Builder uses to allow you to connect variables to UI items in its GUI, and I think Qt uses the technique for their "moc" precompiler.
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.
I'm currently writing a program that should be working on both Windows and Linux. The program uses dynamic modules (LoadLibrary/dlopen) to simplify deployment of different functions.
The Linux part works just fine: The main program exports functions and variables with -Wl,--export-dynamic so the modules can access them, and the modules can be compiled with gcc's -shared option without the requirement to resolve all symbol dependencies when linking.
With Windows (using MSVC 2010), this seems not to work. I'm exporting functions and variables from the main program using __declspec(dllimport), but I am not able to access functions and variables from the main program because linking fails (unresolved external, LNK1120).
How to deal with this? Thank you.
Edit (code sample):
core-file.cpp
#include "core-file.hpp"
Cls_A cls_instance;
void Cls_A::do_something() {
while(0);
}
core-file.hpp
#ifdef TEST_EXPORTS
#define TEST_API __declspec(dllexport)
#else
#define TEST_API __declspec(dllimport)
#endif
class TEST_API Cls_A {
public:
void do_something();
};
extern Cls_A cls_instance;
module.cpp
#include "core-file.hpp"
TEST_API int my_init_function() {
cls_instance.do_something();
return 0;
}
__declspec(dllimport) is for when you're compiling the the program that uses the DLL. When you compiling the actual DLL, you want to use __declspec(dllexport).
Your use of these must be consistent. The typical idiom is to define a macro that will use dllimport and dllexport based on the presence of a macro. In the project the builds the DLL, you define the macro that means to export the functions, and in other projects you don't define it, which means to import them:
#ifdef PROJECT_NAME_BUILD_DLL
#define DLL_SYMBOL __declspec(dllexport)
#else //PROJECT_NAME_BUILD_DLL
#define DLL_SYMBOL __declspec(dllimport)
#endif //PROJECT_NAME_BUILD_DLL
DLL_SYMBOL void SomeFunction(Type value);
The project that builds the DLL will define PROJECT_NAME_BUILD_DLL; projects that use the DLL which include this header do not define this.
On Windows, when you want to link against exported symbols you have to remember to specify all the import libraries that were generated when you linked the modules whose symbols you want to import. (You can just leave the symbols unresolved on Linux because the executable format is different and it's possible to defer symbol resolution to load time.)
I created a static Qt library by using VS2005.
It created an extra file "test_global.h" besides expected ones(test.h and test.cpp).
test_global.h
#ifndef TEST_GLOBAL_H
#define TEST_GLOBAL_H
#include <Qt/qglobal.h>
#ifdef TEST_LIB
# define TEST_EXPORT Q_DECL_EXPORT
#else
# define TEST_EXPORT Q_DECL_IMPORT
#endif
#endif // TEST_GLOBAL_H
Why this file is generated, how I suppose to use it?
Thanks.
You mark your class (or methods) as exported in your library headers:
class TEST_EXPORT TestClass {
// ...
};
Then in your library pro file you add:
DEFINES += TEST_LIB
So during the dll compilation your class header will have "Q_DECL_EXPORT" macro which is Qt way to tell the linker "export this class/method", and when you use your dll in some application, the header will have "Q_DECL_IMPORT" macro.
For more information, check the Qt documentation.
I have a DLL which contains a class with static members. I use __declspec(dllexport) in order to make use of this class's methods. But when I link it to another project and try to compile it, I get "unresolved external symbol" errors for the static data.
e.g.
In DLL, Test.h
class __declspec(dllexport) Test{
protected:
static int d;
public:
static void m(){int x = a;}
}
In DLL, Test.cpp
#include "Test.h"
int Test::d;
In the application which uses Test, I call m().
I also tried using __declspec(dllexport) for each method separately but I still get the same link errors for the static members.
If I check the DLL (the .lib) using dumpbin, I could see that the symbols have been exported.
For instance, the app gives the following error at link time:
1>Main.obj : error LNK2001: unresolved external symbol "protected: static int CalcEngine::i_MatrixRow" (?i_MatrixRow#CalcEngine##1HA)
But the dumpbin of the .lib contains:
Version : 0
Machine : 14C (x86)
TimeDateStamp: 4BA3611A Fri Mar 19 17:03:46 2010
SizeOfData : 0000002C
DLL name : CalcEngine.dll
Symbol name : ?i_MatrixRow#CalcEngine##1HA (protected: static int CalcEngine::i_MatrixRow)
Type : data
Name type : name
Hint : 31
Name : ?i_MatrixRow#CalcEngine##1HA
I can't figure out how to solve this. What am I doing wrong? How can I get over these errors?
P.S. The code was originally developed for Linux and the .so/binary combination works without a problem
EDIT: In the given case, the static variables are not directly referred by the application but the method is inlined since it's in the header. I was able to resolve the link errors by moving the methods to the .cpp file.
In this thread at cprogramming.com it is suggested that a static variable is local to the dll and not exported.
Summary of discussion below
The static member is not accessed directly by code in the calling application, only through member functions of the class in the dll. However there are several inline functions accessing the static member. Those functions will be inline expanded into the calling applications code makeing the calling application access the static member directly. That will violate the finding referenced above that static variables are local to the dll and cannot be referenced from the calling application.
My guess is that the class which uses the DLL should see dllimport instead of dllexport in the header. If I am correct, this can typically be achieved by defining a preprocessor macro like:
#ifdef EXPORTING
#define DECLSPEC __declspec(dllexport)
#else
#define DECLSPEC __declspec(dllimport)
#endif
and then use it in the class declaration:
class DECLSPEC Test{
protected:
static int d;
public:
static void m(){}
}
So that in Test.cpp (or wherever it makes sense in your DLL project) you can specify that you are exporting so that it will be exported with dllexport:
#define EXPORTING
#include "Test.h"
int Test::d;
while the other project, which does not define EXPORTING, will see dllimport.
Does it make sense?
With Windows DLLs, there is a specific distinction between __declspec(dllexport) vs __declspec(dllimport), dllexport should be used when compiling the DLL, dllimport should be used when compiling programs that link to this DLL. The standard way of defining this would be with a macro.
The following is the visual studio example:
// 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 DLL_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
// DLL_API functions as being imported from a DLL, whereas this DLL sees symbols
// defined with this macro as being exported.
#ifdef DLL_EXPORTS
#define DLL_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)
#endif
Despite the summary, one can export static data from a DLL. However, there is a problem that comes up with the standard macros supplied by the Visual Studio DLL project:
#ifdef DLL_EXPORTS
#define DLL_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)
#endif
If you have multiple DLLs calling code from one DLL to another or between EXE and DLL, there is going to be a problem with this macro because every header is going to be exporting. One needs unique macros that handle __declspec. The safest way to handle this problem is as follows:
#ifdef MYPROJECT_DLL_EXPORTS
#define MYPROJECT_API __declspec(dllexport)
#else
#define MYPROJECT_API __declspec(dllimport)
#endif
Then only in the compiler preprocessor options for the DLL project define MYPROJECT_API.
In your header code:
struct/class MYPROJECT_API myclass {
static int counter;
};
And in a .cpp file:
int myclass::counter = 0;
Although it's kinda an old post. I would like to add that (for some reason) to resolve this problem I needed to add the (Windows) __declspec(dllexport)/(import) also INSIDE the .cpp file so the outside code could access it.
// From another answer to ilustrate this =)
#ifdef DLL_EXPORTS
#define DLL_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)
#endif
some_app.h
class DLL_API SomeApp
{
static void MyFunc();
}
some_app.cpp
DLL_API void SomeApp::MyFunc()
{
// Some impl of my app.
}
In my case that was specially required because my functions are templated. Maybe this could work for someone else too.
use inline for c++17
static inline std::string static_variable