Let's say my dll contains the following:
mydll.h
extern "C" void __declspec(dllexport) __stdcall f();
Usually in my app when performing static dll linking I just include the header as it is, but reading a bit about dllexport vs dllimport specifications I wonder if my app should be using the following prototype instead:
extern "C" void __declspec(dllimport) __stdcall f();
I'm using C++ Builder XE6 for both dll and app.
So, what is the proper way to do it?
Most libraries use the preprocessor to do this for you.
They contain a define for __declspec(dllimport/export)
#ifdef MYDLL_EXPORTS
#define MYDLL_API __declspec(dllexport)
#else
#define MYDLL_API __declspec(dllimport)
#endif
void MYDLL_API __stdcaall f();
When the library creator builds the DLL, they define MYDLL_EXPORTS and export the functions, when a client includes the header that isn't defined and they will import the functions.
You'll have to use macros to make sure that you use:
extern "C" void __declspec(dllexport) __stdcall f();
when you build the DLL and
extern "C" void __declspec(dllimport) __stdcall f();
when using the DLL.
See What does this c++ class declaration mean? for some ideas.
If your DLL exports only undecorated C functions (extern "C"), then you can skip all the non-standard attributes and use a .DEF file to export the necessary functions. This is a nice option if your DLL offers a small number of C-compatible APIs.
In theory, you can use a .DEF file with decorated functions (including C++ member functions), but it's not usually worth the effort. You first have to figure out exactly how each function was decorated (mangled) and then manually add those to the .DEF file.
If you want to export C++ interfaces, then you need to use the both __declspec(dllexport) and __declspec(dllimport) as shown in the other answers.
Related
I am trying to understand some code that I have inherited, but am having some trouble googling my way out of it, and have some questions I hope some of you can help me with. The code can be seen just below, and is a .hpp (c++ header file) which declares a function.
#ifdef _MSC_VER
#define EXPORT_SYMBOL __declspec(dllexport)
#else
#define EXPORT_SYMBOL
#endif
#ifdef __cplusplus
extern "C" {
#endif
EXPORT_SYMBOL float func(int int_param, float float_param);
#ifdef __cplusplus
}
#endif
My first point of confusion is
#ifdef _MSC_VER
#define EXPORT_SYMBOL __declspec(dllexport)
#else
#define EXPORT_SYMBOL
#endif
I understand this as "if we are compiling from a windows machine, do something special".
What does __declspec(dllexport) do exactly?
Why do I need EXPORT_SYMBOL at all?
Secondly I am confused about the necessity of wrapping the header in the extern "C" statement. As far as I can tell the header is checking to see if __cplusplus is defined, that is, if we are compiling with g++. The extern block is here to make sure I don't have issues with the g++ compiler if func() was found in say, a file called func.c instead of a .cpp file, and then compiled with gcc. I understand mangling, and how g++ changes function names to enable overloading.
As i have it contained in a .cpp file and hence intend to exclusively compile it with g++, do I need the extern "C" block, and #ifdef statements? Is there a case where this is crucial?
What does __declspec(dllexport) do exactly?
When DLL is created, it does not export any symbols by default (unlike static library). In Visual C++, __declspec(dllexport) is the easiest way to export symbols. There are other ways to export.
As i have it contained in a .cpp file and hence intend to exclusively
compile it with g++, do I need the extern "C" block, and #ifdef
statements? Is there a case where this is crucial?
This allows using the function if you load the DLL from a C program, from a C++ program built by any compiler, or even from other languages with C bindings. If you work exclusively with C++ and g++ compiler, there is still a case when this is important: loading the DLL dynamically - in which case you need to supply your function name as a string (mangled unless you use extern "C").
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).
I want to export a decorated function name in a def file like this:
LIBRARY Example
EXPORTS
??0__non_rtti_object#std##QAE#ABV01##Z=myfunc #1
The Problem is that the linker strips the function name at the first #-sign and places just
"??0__non_rtti_object" into the export table. My question is now, if there is a way to include
the #-characters as well? I use Visual Studio 2010. Maybe there is someone who can help me.
Thanks in advance, Hannes.
Preamble
You didn't answer my comment about the use of the .DEF file, so I assume you must be unfamiliar with the the dllexport and dllimport qualifiers. With them, there is no need for the .DEF file to export symbols.
If there is a particular need for the .DEF file that invalidate the use of the dllimport/dllexport feature, please ignore the following.
How to use dllimport/dllexport?
In your public header (say, public.hpp), write something like:
#ifdef MY_PROJECT_EXPORTS
#define MY_PROJECT_API __declspec(dllexport)
#else
#define MY_PROJECT_API __declspec(dllimport)
#endif
This way, the macro MY_PROJECT_API will enable the export/import of your symbols. For example, later, in the same public.hpp, you can declare:
// A global variable
MY_PROJECT_API int myGlobalVariable ;
// A function
MY_PROJECT_API void my_function() ;
// A class or struct
class MY_PROJECT_API MyClass
{
public :
int i;
virtual int foo() ;
// etc.
} ;
Then, what you need to do is, in the project options of your library, define the MY_PROJECT_EXPORTS: This way, when you compile your library, the symbols above are declared dllexport, and when someone else includes your public.hpp header, the symbols above will be dllimport
And if your code is cross-platform (dllimport/dllexport is a MS compiler feature), just wrap the defines above around a compiler test. For example:
#ifdef _MSC_VER
// For MS Visual Studio
#ifdef MY_PROJECT_EXPORTS
#define MY_PROJECT_API __declspec(dllexport)
#else
#define MY_PROJECT_API __declspec(dllimport)
#endif
#else
// For other compilers
#define MY_PROJECT_API
#endif
About the .DEF file?
The .DEF file was used before, when exportable C functions were still "the way to go" on Visual Studio.
For strong type safety, C++ decorate its symbols.
The downside is that each compiler has its own decoration scheme (which never bothered me in 12-years of development), and that finding the exact, decorated name of a symbol can't be painful.
But the merits of that is that:
You can now export overloaded/namespaced functions/symbols
the parameter types are part of the ABI, meaning the linker can verify you aren't screwing up or cheating with your types
The dllimport and dllexport features have the following advantages:
it enables the export to be done at source level, instead of using yet another project file
the programmer can now ignore the particular decoration scheme (which usually only interests the linker), all the while profiting from the strong type safety of C++ extended to the linker.
Sources
For more information, see:
__declspec : http://msdn.microsoft.com/en-us/library/dabb5z75.aspx
dllexport, dllimport : http://msdn.microsoft.com/en-us/library/3y1sfaz2.aspx
Using dllimport and dllexport in C++ Classes : http://msdn.microsoft.com/en-us/library/81h27t8c.aspx
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
I have some quick questions on windows dll.
Basically I am using the ifdefs to handle the dllexport and dllimport, my question is actually regarding the placement of the dllexports and dllimports as well as extern keyword.
I am putting the dllimports/dllexports on the header files but do I have to put the dllexport and dllimports on the actualy definition?
What about for typedefs?
Do I put the dllimport/dllexport in front? as in
dllexport typedef map<string, int> st_map
Also regarding the extern keyword I have seen it being used like this:
extern "C" {
dllexport void func1();
}
I have also seen it being used like this:
extern dllexport func1();
One includes the "C" and the other does not, my question is what is the difference and do I need to use it? If I do then do I use it for both dllexport and dllimport also do I have to use it on both the header file declarations and the definitions?
My project is going to be shared library, it contains several class files which I want to export, some typdefs i want to export and some global functions which I also want to export all into a dll.
Anyone enlighten me please?
EDIT:
Okay I thought I'll post a small extract of what i've done, also notice that I am building the library for both linux and windows so I do a check for that:
mydll.h
#ifdef WINDOWS
# ifdef PSTRUCT_EXPORT
# define WINLIB __declspec(dllexport)
# else
# define WINLIB __declspec(dllimport)
# endif
#else
# define WINLIB
#endif
WINLIB void funct1();
Now in the source code:
mydll.cpp
#define PSTRUCT_EXPORT
void funct1() <---- do I need to add WINLIB in front of it?
Or is doing it in the header enough?
First, you don't need to import or export typedefs. As long as they're in the header files that both sides use, you're good. You do need to import/export functions and class definitions.
Presumably you use the same header files for both the importing and exporting code, so you could do some makefile magic to define a preprocessor macro on each side, then do something like this:
#if defined( LIBRARY_CODE )
#define MYAPI __declspec(dllexport)
#else
#define MYAPI __declspec(dllimport)
#endif
extern MYAPI void func1();
class MYAPI MyClass {
...
};
Regarding C vs. C++ functions, you can do this:
#if defined( __cplusplus__ ) // always defined by C++ compilers, never by C
#define _croutine "C"
#else
#define _croutine
#endif
extern _croutine void function_with_c_linkage();
Make sure you import this header file from your C++ source file (containing the implementation of this function) or the compiler won't know to give it C linkage.
typedefs do NOT need a dllimport/dllexport, it's just a definition
dllimport/dllexport are not standard, think of defining a macro for other platforms/compilers
also take care of the calling convention (cdecl,stdcall,...) used otherwise you'll run into problems (if you need to be interoperable with Visual basic use stdcall)
enclose within extern "C" so that your lib can be used from within C++ programs, use #ifdef __cplusplus to keep it only visible to C++.
Have a look at different OpenSource libs. There you'll find plenty of examples on how making a good library header. There could be issues with name decoration in the case of C++ without the extern "C".