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".
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").
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.
I am creating a c++ dll to be imported in vb.net.
I have found that the best way to organize the imports and exports in the header file of the dll, is something of the following type:
#ifndef MY_DLL_EXPORTS
#define MY_DLL_EXPORT __declspec(dllexport)
#else
#define MY_DLL_EXPORT __declspec(dllimport)
#endif
#ifdef __cplusplus
extern "C"
{
#endif
MY_DLL_EXPORT BOOL my_function(uint32_t x);
#ifdef __cplusplus
}
#endif
My question is, where are the __cplusplus and MY_DLL_EXPORTS supposed to be defined ?
I have not done this before and I can't seem to find a place in the code for it. I read something about putting these definitions in the
Project Properties -> Configuration Properties -> C/C++ -> Preprocessor -> Preprocessor Definitions
Do I put them in the DLL's project properties ? and if i do, on using this DLL, will they always be defined so the if statement will always go to the dllimport ?
Also, is __cplusplus already defined or must I define it ?
__cplusplus is defined for you by a C++ compiler, but NOT by a C compiler. This is how you can determine if your code is being compiled by a C or C++ compiler. That's why this is used to guard the extern "C" construct. A C compiler would just omit it (since it emits C linkage already).
The other constants can be either defined on the compiler's command line (eg. in the menu you listed), or in the code somewhere:
#define MY_DLL_EXPORTS
Best place to define COMPILING_DLL 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.
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