Probably a simple question but I only have Linux to test this code on where __declspec(dllexport) is not needed. In the current code __declspec(dllexport) is in front of all files in the .h file but just in front of like 50% of the functions in the cpp file so I am wondering if they are really needed in the cpp file at all ?
No, its only needed in the header.
Here's a link with more info.
Expanding on what Vinay was saying, I've often seen a macro defined
#if defined(MODULENAME_IMPORT)
#define EXPORTED __declspec(dllimport)
#elif defined(MODULENAME_EXPORT)
#define EXPORTED __declspec(dllexport)
#endif
Then in your header you do
void EXPORTED foo();
set the defines accordingly in the project settings for the project doing the import/exporting.
No, it is not required in cpp file. Only in declaration it is required.
For Example if I have a class CMyClass. If I want to export this then .h will have
.h Server code
__declspec(dllexport) CMyClass
{
};
In the client code i.e., which uses this class you have to forward declare the class as
Client code
__declspec(dllimport) CMyClass;
// Code to use the class
You may use in .cpp file also when you have templated code and you are instantiating in .cpp file then you need to export the definition when it is instantiated. But even in this case, I have seen that doing in .h also works. On windows you can use dumpbin.exe /exports *.dll to see what signatures are exported, there is similar utility in Linux too. This will give you an idea how signature is exported.
Related
#if COMPILING_DLL
#define DLLEXPORT __declspec(dllexport)
#else
#define DLLEXPORT __declspec(dllimport)
#endif
How / where do I define COMPILING_DLL ?
Seen here:
what does __declspec(dllimport) really mean?
Sounds like I can't use load-time dynamic linking at all if I can't use the same header?
One another option:
Use the default defined macro local to the project.
You can see the default defined macros local to the project in the below location:
Properties -> C/C++ -> Preprocessor -> Preprocessor Definition.
Example:
Suppose your Project Name is: MyDLL
Default Macro Local to that project: MYDLL_EXPORTS
#ifdef MYDLL_EXPORTS
/*Enabled as "export" while compiling the dll project*/
#define DLLEXPORT __declspec(dllexport)
#else
/*Enabled as "import" in the Client side for using already created dll file*/
#define DLLEXPORT __declspec(dllimport)
#endif
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.
In the DLL project, you add a #define (either in a header file or in the project properties) for COMPILING_DLL. As this will not be set for any other project (especially if you name it something better than COMPILING_DLL) then the #if directive will work properly.
You (actually Visual Studio in ideal cases) defines the COMPILING_DLL as an argument to the compiler when you build the DLL. So, it will default to __declspec(dllexport). On the other end, when you USE the DLL's header file, you don't define this, so DLLEXPORT will be evaluated by default to __declspec(dllimport).
If you use CMake to generate your build configuration, you should be able to use
the macro <projectname>_EXPORTS the way you want to use COMPILING_DLL, where projectname was defined with the CMake command project(projectname):
A preprocessor macro, <target_name>_EXPORTS is defined when a shared library compilation is detected.
source
I tested and it works on Windows using the Ninja generator with compiler MSVC from Visual Studio 2015 Express.
Related: CMake adds -Dlibname_EXPORTS compile definition
You can't define function body that way in the header file. It is prohibited by __declspec(dllimport). This specifier can only be specified on function declaration, not definition.
You have to move the function body to a source file.
in header file:
extern DLLEXPORT void test2();
In .cpp file:
void test2()
{
// ...
}
As folks said, don't forget to add COMPILING_DLL to the project preprocessor definitions.
Actually, the real problem is the preprocessor directive.
You should use #ifdef and not #if to test if the variable is really defined (and we don't care about the defined value or if there is any).
NOTE: I know this thread is 1-year old but it still may be useful for somebody who have this problem in the future.
If I have SOME_MACRO which is defined as either __declspec(dllimport) or __declspec(dllexport), is there a way to check at compile time which one is being used?
I.e. something like this:
#if SOME_MACRO == __declspec(dllimport)
// do something
#else
// do something else
#endif
UPD.
Looking at the answers I'm getting I guess I should be more specific in why I need this.
I'm trying to compile a rather big 3rd party library, which has a function declared as dllexport in most parts of their code where it's included. There's however one component in which it's a dllimport.
I need to modify the declaration slighly for the dllimport case. The switch between the two declarations is not very simple, it is a result of quite a deep tree of #ifdef instructions spread across several files. In principle I could dig this info out form these instructions, but to be sure I did it correctly I'd have to try and compile the whole library under several different configurations (each compilation taking a couple hours).
If on the other hand there was a simple way check whether their SOME_MACRO is evaluated to import or export, I could test this on a small program quickly and safely put that inside the library.
You cannot use
#if SOME_MACRO == __declspec(dllimport)
__declspec(dllimport) is not a valid token for a preprocessor expression.
Your best option is to use another preprocessor macro, such as:
// Are we building the DLL?
#if defined(BUILD_DLL)
// Yes, we are.
#define SOME_MACRO __declspec(dllexport)
#else
// No. We are using the DLL
#define SOME_MACRO __declspec(dllimport)
#endif
Now, you can use:
#if defined(BUILD_DLL)
to include conditional code depending on whether you are building the DLL or using the DLL.
Practically speaking, that ends to be a little bit more involved.
Most projects have more than one DLL. BUILD_DLL is not going to work. You will need BUILD_xxx_DLL for each DLL you build. Let's say you have two DLLs, utility and core. and an application that depends on both.
You may also need to create a static library.
You will need something like the following in every public .h file of the utility library.
#if defined(BUILD_UTILITY_STATIC)
#define UTLIITY_EXPORT
#elif defined(BUILD_UTILITY_DLL)
#define UTLIITY_EXPORT__declspec(dllexport)
#else
#define UTLIITY_EXPORT__declspec(dllimport)
#endif
Of course, you don't want to have to repeat the same code in lots of .h files. You will create a .h file that contains the above and #include that in all other .h files.
When building utility.dll, you will need to define BUILD_UTILITY_DLL and leave BUILD_UTILITY_STATIC undefined.
When building utllity.lib (static library), you will need to define BUILD_UTILITY_STATIC and leave BUILD_UTILITY_DLL undefined.
Users of utility.dll will leave BUILD_UTILITY_STATIC as well as BUILD_UTILITY_DLL undefined.
Users of utility.lib (static library) will need to define BUILD_UTILITY_STATIC and leave BUILD_UTILITY_DLL undefined.
You will need a similar file for core.dll and core.lib.
The macro is named by you the DLL creator.
You want a header file that works in export or import mode.
A C/C++ file will be used, to create a program, to build the DLL (export).
Other C/C++ files will be used to call the DLL (import functions).
In the build implementation file a macro, that you name, is defined before the inclusion of the header.
e.g.
#define DLLNAME_BUILD_DLL
#include "dll_header.h"
In the header, if the macro is defined, the mode is set to export. When using the DLL the macro is not defined and the functions are imported.
I have inherited a Linux project that I need to port to Windows and Visual Studio. I have setup the same project structure as was the case in Linux but I find the structure a bit strange (maybe it is all good in Linux) and I believe that's what's causing the LNK4217 (locally defined symbol 'symbol' imported in function 'function') and C4273 ('function' : inconsistent DLL linkage) warnings I receive. I would like some advice on how to re-structure the project or change the code to avoid these warnings. Basically this is what I have:
Dll project called Foo
Dll project called Bar (depends on the Foo dll)
The part that I find strange and what I believe causes the LINK4217 and C4273 warnings is that both the Foo and Bar library contain the header and source file for the class MyClass (the warnings mention this class):
//MyClass.h
class BAR_API MyClass
{
//Methods etc.
}
Where BAR_API is defined as __declspec(dllexport) in the Bar library while in the Foo library it is __declspec(dllimport) according to:
#ifdef BAR_EXPORTS
#define BAR_API __declspec(dllexport)
#else
#define BAR_API __declspec(dllimport)
#endif
How do you propose I change this? Would it help to move MyClass to its own library and have Foo and Bar include it or change so that BAR_API is defined as nothing instead of __declspec(dllimport) in the Foo library?
Let's see what you have here
1. Foo.dll that defines MyClass and exports it
2. Bar.dll that depends on Foo.dll, but also defines MyClass - and this is the source of ambiguity that confuses your linker.
The right thing, to my understanding, is to:
Define MyClass in Foo.dll (since Bar.dll already depends on it) and export MyClass using __declspec(dllexport) in Foo.dll's MyClass declaration.
#include header file that declares MyClass (where it will be specified as imported using __declspec(dllimport)) where appropriate in the Bar.dll's .cpp files; however, do not include the .cpp file that implements MyClass.
BAR_API (which in this case should be renamed to FOO_API) helps you achieve this by being defined as either dllexport or dllimport based on whether BAR_EXPORTS (which in this case should be renamed to FOO_EXPORTS) is defined. You should #define FOO_EXPORTS in every source file in the Foo project either by setting compiler command line parameter or by #including common header that #defines FOO_EXPORTS in every .cpp file in the Foo project (but not in the Bar project).
This way both Foo.dll and Bar.dll will use MyClass from the Foo.dll.
HTH
I am using dev c++. also i am getting assistant from a library, developed by somebody else for my own c++ projects. i have added two new classes called TriangleList and TriangleLists to the library as i wanted new class types for the project. once, i added the hpp and cpp files to the library, i got the massage like creating ../lib/libExtraction.a .
however, when i called back the functions, that i written in the new classes, from my own project, i got the error massages like
`[Linker error] undefined reference to `TriangleLists::Erase()`
(the above one for the Erase function)
then, when i removed the .cpp file and wrote everything in .hpp it works.
But, i would like to maintain two files for the hpp and cpp further. so, please tell me how to solve this link error problem as i want to learn this. thank you in advance.
First thing you need to check is if you're exporting the class:
class __declspec(dllexport) TriangleLists
{
//members
};
When you include the header in a different project however, you need to specify that the class is imported, so:
class __declspec(dllimport) TriangleLists
{
};
This is usually achieved with preprocessor directives:
#ifdef BUILDING_FIRST_PROJECT
#define DLLIMPEXP _declspec(dllexport)
#else
#define DLLIMPEXP _declspec(dllimport)
#endif
//TriangleLists.h
class DLLIMPEXP TriangleLists
{
}
and only define BUILDING_FIRST_PROJECT in your first project. That way, when building the first project, you'll be exporting the class, and when you include the header in another project, you're importing it.
Second thing is that the other project must link to the .lib file generated by the first project.
The reason it works when you move the implementation to the header is that the method becomes inline, so there's no lookup for it in the lib files, as it's definition is already known.
I have a dll with a class that define some methods and variables inside it. I marked it as
__declspec(dllexport)
and i imported the .h header inside a win32 application project in the same solution. I can use the functions but when I try to compile the project I have a lot of errors about external symbols not resolved. Why?
Please read about the standard way of using macros for this very common task here: http://wiki.tcl.tk/8721
The basic idea is that you define a macro, say MY_API like so:
#ifdef BUILD_MYAPI
# define MY_API __declspec(dllexport)
#else
# define MY_API __declspec(dllimport)
#endif
When you declare a function or a class in the header file you do this:
void MY_API myApiFunction(int x);
When you build your own dll which declares the body of the function, you add the definition of BUILD_MYAPI to the build. This makes all declerations to be dllexport
when you include the header from some other dll you don't add BUILD_MYAPI so the decelerations are dllimport
When compiling with visual studio, you can add a macro definition to the compilation without changing the source from project properties -> C/C++ -> Preprocesson -> Preprocessor definitions
For the application where you want to import that class, you will need to mark the class as
__declspec(dllimport)
Instead of dllexport.
You must also make sure to link with the import library of the DLL (a .lib file).