These days to write a few small program practiced hand, when preparing to export a class, I found that I do not know if the extension DLL without MFC, how to export. But I know dllexport can export functions and variables, and MFC extension DLL even use MFC's functionality, but the ability to export the class should also not have to use MFC can do, there must be a corresponding mechanism can be achieved. So I looked at MSDN, and found that this mechanism is simply scary, and the original is the same as the export function, the Dllexport keyword added to the class name before you can. It is estimated that the same classmates as me, the MSDN related documents translated, attached to my comments, hope to be useful to everyone.
The commentary program is tested in Visual Studio.NET 2005 Professional to get results, and the code given has omitted a large number of statements, leaving only the part that is most relevant to the topic, and therefore may not compile.
The MSDN documentation is selected from the April 2007 update of the MSDN Library.
Using DllImport and dllexport in C + + Classes
Using DllImport and dllexport in C + + classes
Microsoft specific
You can declare C + + classes with the DllImport or dllexport attribute. These forms imply the entire class is imported or exported. Classes exported this is called exportable Classes.
The following example defines an exportable class. All its member functions and static data is exported:
You can use the DllImport and Dllexport properties when declaring a C + + class. These two forms implicitly import or import an entire class. Classes that are exported by this method are called exportable classes.
The following example defines an exportable class, and all of its member functions and static will be exported:
#define DllExport __declspec (DllExport)
Class DllExport C {
int i;
virtual int func (void) {return 1;}
};
Note that explicit use of the DllImport and dllexport attributes in the members of a exportable class is prohibited.
Note that it is forbidden to explicitly use the DllImport and Dllexport properties on members of an exportable class.
Balon Note: If you cannot write like this:
#define DllExport __declspec (DllExport)
Class DllExport C {
DllExport int i; You cannot use dllexport on a member
DllExport int func (void) {return 1;}//Can not be used on members DllExport
};
Dllexport Classes
Exporting classes through dllexport
When you declare a class dllexport, the all it member functions and static data members is exported. You must provide the definitions of all such members in the same program. Otherwise, a linker error is generated. The one exception to this rule applies to pure virtual functions, for which you need not provide explicit definitions. However, because a destructor for an abstract class are always called by the destructor for the base class, pure virtual de Structors must always provide a definition. Note that these rules is the same for nonexportable classes.
If you export data of class type or functions this return classes, be sure to export the class.
When you declare a class as dllexport, all of its member functions and static data members are exported. You must define all such members in the same program, or you will create a link error.
Balon Note: As in the following export class, Func must be defined in this DLL's project or in a program that uses a DLL, otherwise there will be a link error for unresolved external symbols when used. Note that a definition can be placed in a DLL or in a user project of a DLL, as long as it is defined before it is used.
Method one: defined in the DLL project and used directly in the user project.
Dll.h
#define DllExport __declspec (DllExport)
Class DllExport C {
int func (void);
};
Dll.cpp
int C::func (void)
{
return 1;
}
Method Two: There is only one declaration in the DLL project, there is no definition. The definition of the function can be given before the user is used. In addition, if you do not use Func at all in the user program, you can not provide its definition and link errors.
Dll.h
#define DllExport __declspec (DllExport)
Class DllExport C {
int func (void);
}; Client.cpp
int C::func (void)
{
return 1;
}
int main ()
{
c C;
C.func (); Ok
return 1;
}
The only exception to this rule is that for pure virtual functions you can not provide a definition of the display.
Balon Note: As the pure virtual function func in the following example, you do not have to provide a definition. Because this exported class may itself be an abstract class, Func is a function that is not implemented, and certainly does not provide a definition.
However, because the destructor of the abstract class is always called by the destructor of the base class, the pure virtual destructor must provide a definition. This rule also applies to non-exportable classes.
Balon Note: Based on my test results, a table is listed for the compilation results in various cases:
DLL project does not have the corresponding function definition of the compilation results client application usage
member functions are normally linked. You can define an instance of this class, do not call this member function for normal linking, and call this member function link error, prompting this function to be a pending external symbol.
An error occurred in the virtual member function link, which indicates that the function is a pending external symbol. -
Pure virtual member function normal link. Cannot define such an instance, compile error, hint cannot instantiate an abstract class.
destructor Normal link. Link error indicating that the destructor is a pending external symbol
The virtual destructor link error indicates that the destructor is a pending external symbol. -
The pure virtual destructor link error indicates that the destructor is a pending external symbol. -
It can be seen that the rules in the document are true, and pure virtual destructors are treated as virtual destructor functions. Another question is why virtual functions (including destructors) must be defined in the project in which they are declared, while ordinary functions do not have to be. My analysis causes are estimated as follows:
We know that if a C + + class has a virtual function (including the case where its base class has virtual functions), the C + + compiler generates a virtual table for it at compile time and, in the constructor, fills in the corresponding virtual table's first address into the virtual table pointer member of the class instance. If a virtual function is implemented more than once in a derived system, the virtual table is populated with the lowest level (most-derived) implementation. The process is that the base class object is constructed first, and its constructor fills in the base class's virtual table implementation entry (which is why, calling the virtual function in the constructor only calls to the implementation of the current class hierarchy, unable to invoke the reason for the implementation of the derived class), then the derived class is constructed, and its constructor fills in the virtual table entry , overwriting the entry address of the base class record. This process continues until the entire object construction is complete.
In fact, the key point of all this is that the constructor must know the virtual table entry address of the current class, and this needs to know the entry address of all the virtual functions that are filled out in the empty table! Otherwise, the compiler will not be able to generate the function of the constructor's empty table. So the compiler had to start complaining.
Therefore, all virtual functions must be defined in the project in which they are declared, and their entry addresses can be correctly found at link time so that the compiler can generate the constructor's fill table function.
If you export a data member of a class type, or a function that returns a class, be sure to export that class.
Balon Note: This is a guideline, not a mandatory compile link requirement. You do not have to export the class as long as you do not use the member function of the returned class, and the return class does not have a virtual table. But most of the cases are to be exported, so as a good principle, follow MSDN's advice to do just fine. This is described in more detail in the next article of this article.
DllImport Classes
Importing classes through DllImport
When you declare a class DllImport, the all it member functions and static data members is imported. Unlike the behavior of DllImport and dllexport on nonclass types, static data section cannot specify a definition in the S AME program in which a DllImport class is defined.
When you declare a class as DllImport, all of its member functions and static data members are imported. Unlike using DllImport and dllexport on non-class types, it is not possible to give the definition of a static data member in the same program that has the definition of the DllImport class.
Balon Note: This sentence translation of some of the tongue, the original is not where. In fact, read through the Dllexport Export class section of the annotations, it is good to understand here to say the meaning. This means that static data members cannot be defined in the user project, as in other member functions, but not in the DLL itself project.
Method One, define static data members in the DLL as required:
Dll.h
#define DllExport __declspec (DllExport)
Class DllExport C {
static int x;
};
Dll.cpp
int c::x = 0;
Client.cpp
int main ()
{
c C;
c.x = 10; Ok
return 1;
}
Method two, attempting to "give the definition of a static data member in the same program that has the definition of the DllImport class", there is a compile error when the client program compiles:
Dll.h
#define DllExport __declspec (DllExport)
Class DllExport C {
static int x;
}; Client.cpp
int c::x = 0; C4273
int main ()
{
c C;
c.x = 10;
return 1;
}
inheritance and exportable Classes
inherit with exportable class
all base Classes of a exportable class must be exportable. If not, a compiler warning is generated. Moreover, all accessible members, is also classes must be exportable. This rule permits a dllexport class to inherit from a DllImport class, and a DllImport class to inherit from a dllexport C Lass (though the latter is not recommended). As a rule, everything that's accessible to the DLL's client (according to C + + access rules) should be part of the Exporta Ble interface. This includes private data referenced in inline functions.
All base classes for an exportable class must be exportable, or a compilation error will occur.
Balon Note: In fact, this rule is not certain, in the case of satisfying certain conditions, the base class non-exportable program is also normal. Of course, most of the cases are still to be exported, and the recommendations are done as MSDN requires. This is described in more detail in the next article of this article.
In the following example, a is an exportable class, and A's base class base should also be an exportable class.
#define DLLEXPORT   __DECLSPEC (DllExport)
class DllExport A:public Base
{
//...
};
In addition, all accessible class type members must also be exportable. This rule allows a dllexport class to derive from a DllImport class, or a DllImport class derived from a Dllexport class (although the latter is not recommended).
Balon Note: In the following example, base is a DllImport class,
Basedll's header file basedll.h
#define DllImport __declspec (DllImport)
Class DllImport Base
{
}; Deriveddll's header file Deriveddll.h
#include "basedll.h"//include a DllImport class declaration in
#define DllExport __declspec (DllExport)
Class DllExport A:public base//A derives from DllImport class base
{
// ...
};
As a result, everything that the client of this DLL can access (in accordance with C + + 's access rules) should be part of the export interface. Includes private members that are referenced by the inline function.
Balon Note: This sentence is actually the most important sentence in the full text, in fact, this document if the sentence unfolded to say clearly, do not need me here to write this article. In the next article of this article there will be an in-depth discussion of this sentence
Selective Member Import/export
Selective member Import Export
Because member functions and static data within a class implicitly has external linkage, you can declare them with the DL Limport or dllexport attribute, unless the entire class is exported. If the entire class is imported or exported, the explicit declaration of member functions and data as DllImport or Dllexpo RT is prohibited. If you declare a static data member within a class definition as dllexport, a definition must occur somewhere within the S Ame program (as with nonclass external linkage).
Because member functions and static data in a class are implicitly externally linked, you can add DllImport or dllexport properties to their declarations without exporting the entire class. If the entire class is imported or exported, explicit DllImport and dllexport are not allowed to declare the member functions and data. If you declare a static data member in a class as dllexport, it should be defined somewhere in the same program (as with non-class external links).
Balon Note: The previous sentences are well understood. The last sentence is actually saying that you can export a static data member as you would with a generic variable that exports a non-class member from a DLL, to be defined in the project where the DLL is located. The method of exporting a common variable is to define this variable in a CPP file in the DLL and add the Dllexport declaration:
Dll.cpp
__declspec (dllexport) int x = 0;
Then, compare the methods of exporting static data members of a class:
Dll.h
#define DllExport __declspec (DllExport)
Class A//Note that there are no export classes a
{
Public
DllExport static int x; That's why you can export individual members here.
}; Dll.cpp
int a::x = 0;
Similarly, you can declare member functions with the DllImport or dllexport attributes. Must provide a dllexport definition somewhere within the same program.
Similarly, you can also add a DllImport or dllexport property to a member function declaration. In this case, you must provide a dllexport definition somewhere in the same program.
It is worthwhile to note several important points regarding selective member import and export:
· Selective member Import/export is best used for providing a version of the exported class interface that's more restricti ve That's, one for which can design a DLLs that exposes fewer public and private features than the language would otherwi Se Allow. It is also useful for fine-tuning the exportable interface:when you know that the client, by definition, was unable to acc ESS Some private data, you need not export the entire class.
· If You export one virtual function in a class, you must export all of them, or at least provide versions that the client C A use directly.
· If you had a class in which you is using selective member Import/export with virtual functions, the functions must is in The exportable interface or defined inline (visible to the client).
· If you define a member as dllexport but does not include an IT in the class definition, a compiler error is generated. You must define the member in the class header.
· Although the definition of class members as DllImport or dllexport are permitted, you cannot override the interface Specifi Ed in the class definition.
· If you define a member function in a place other than the body of the class definition in which you declared it, a warning is generated if the function was defined as dllexport or dllimport (if this definition differs from the. specified in the class declaration).
Some highlights of selective member import and export are worth our attention:
· Selective member import and export is best used to provide a more restrictive version of an exported class interface; That is, allows you to design a DLL to export less public or private features than normal language allows. This is also useful for fine-tuning exportable interfaces: If the client cannot access some private data by definition, you do not need to export the entire class.
· If you export a virtual function in a class, you must export all virtual functions together, or at least provide a version that the user can access directly.
· If you use Selective member import and export on a virtual function of a class, these functions must either be in an exportable interface or inline defined (visible to the customer).
· If you define a member as dllexport, but you do not include the definition in the definition of the class, a compiler error is generated. You must define this member in the header file of the class.
· Although class members are allowed to be defined as DllImport and dllexport, you cannot override the definition of this class.
· If you do not define a member function at the class body definition of the declaring member function, and this member function is defined as dllexport or dllimport, a warning is generated if the definition is not the same as the declaration specified in the class.
END Microsoft Specific
So, what is the underlying mechanism of the whole system? What is the way that allows us to use a class exported from a DLL in another program?
We know that to use a C + + class, the necessary condition is that the header file of this class can be obtained at compile time, and the link address of the corresponding symbol (such as member function, static data member, etc.) can be found during the link period. If this C + + class is in the same project as your user, then this condition is well-satisfied:
First, the C + + class header file is well received. Use the header file of the class directly in the user to include
Second, C + + classes are often used by the compiler as a compilation unit to generate an obj file. During the last link, the linker will link all obj in the project to generate the final binary target file. So when a linker encounters a class member function (or other form of symbolic reference), it finds the link address of the symbol in the obj file generated by the class.
So, using a C + + class in your code, what exactly is needed for the compile and link periods? In other words, what are the conditions that the compiler and linker will not complain about?
According to the definition of the C + + language, a C + + class actually declares or defines the following categories of content:
1. A data structure is declared, a non-static data member in a class, a virtual table entry address pointer that is not visible in the code but is generated if there is a virtual function.
2. Declare and define a bunch of functions whose first parameter is a pointer to the data structure. These are actually non-static member functions (including virtual functions) in the class, although they are written inside a pair of curly braces of the class in the class declaration, but nothing is actually added to the internal data structure described in 1th above. In fact, such a declaration simply adds two properties to these functions: the scope of the function name identifier is limited to the class, and the first parameter of the function is this, which is omitted.
3. Declaring and defining another heap of functions, which appear to be ordinary functions, have little to do with this class. These are actually static functions in the class, and they are the same, not adding anything in the internal data structure as described in 1th, except that the scope of the function name identifier is limited to the class.
4. Declare and define a bunch of global variables. These are actually those static data members in the class.
5. Declares and defines a global variable, which is an array of function pointers that holds the entry addresses for all virtual functions in this class. Of course, this global variable is built on the premise that this class has virtual functions.
Here is an example.
Class MyClass
{
Public
int x;
int y;
void Foo ();
void Bar (int newx, int newy);
virtual void Vfoo ();
virtual void Vbar (int newx, int newy) = 0;
static void Sfoo ();
static void SBar (int newx, int newy);
static int sx;
static int sy;
};
For the class myclass,c++ compiler listed above, most of the compilers are compiled in the following way:
Now let's see why the compiler needs a header file and a symbolic address to compile a link to a program that uses MyClass.
First, because the compiler needs to know the memory layout of the class at compile time, to ensure that the correct memory-opening code can be generated, and those sizeof (MyClass) values. With a header file, the compiler knows that a MyClass occupies 12 bytes of memory (see, two integers and a pointer).
Second, when calling MyClass's member functions, static functions, the linker needs to know the entry address of these functions, and if the entry address cannot be provided, the linker will error.
Finally, when referencing a static data member of MyClass, the linker needs to know the address of these variables, just like referencing an external global object. If the address of these variables cannot be provided, the linker will also error.
Can be seen:
1. Compile time: The header file of the class must be provided so that the compiler can know the size and memory layout of the class instance.
2. Link period: The address of the class's member functions, static functions, and static data members that must be provided by the program, so that the linker can generate the final program correctly.
Here, we can guess, in fact, to export a class, the compiler actually just need to use this class: member functions, static functions, static data members as normal functions, global variables export. In other words, instead of "Exporting a class", we actually export the entry address of the "defined entity" that needs to be referenced in this class as normal functions and variables.
Finally, let's take a look at the DLL that actually generates the MyClass class that exports the preceding columns. With dependence, you can see the following results:
As you can see, except that the Vbar function is a pure virtual function, the entry addresses of other functions and static data members are exported. As you can see, vtable is also exported for reference when manipulating virtual functions.
Balon Vernacular MSDN: Exporting C + + classes from common DLLs (1) How to use –dllexport and DllImport (Chinese-English, annotated)
When I wrote this, I stole a lazy, avoiding a whole bunch of complicated things in a virtual table. Thank you for Houdy's tip, his article for the virtual table, and from the DLL to export the underlying mechanism of the virtual table is detailed analysis, want to this inquisitive classmate must look:
Where is the virtual function table placed?
This article from Csdn Blog, reproduced please indicate the source: http://blog.csdn.net/hxb20082008/archive/2009/09/02/4510494.aspx
[to] export the use of C + + class –dllexport and DllImport from a normal DLL (Chinese-English control, annotated)