C + + DLL export class knowledge Daquan

Source: Internet
Author: User
Tags export class

In the company's use of C + + development, the company's Danale a C + + cross-platform development framework. In the field of C + + development I am still a novice, have a lot of knowledge to learn, such as DLL library development.

Reference to a lot of this information, the DLL has a basic comprehensive understanding. There is a problem that makes me a little confused, the normal way to import and export C + + classes is to use _declspec (dllexport)/_declspec (dllimport) to import the export class, but in the company's development we did not import and export, Instead, it defines a few abstract classes that have only pure virtual functions, and then defines a factory class that registers the factory class with the framework's service center and, when used, gets the factory class from the service center to create other classes in the DLL. I do not understand the use of this way, Google + Baidu search a lot of this content, a lot of blog talk about this way of use, but also did not speak clearly the principle of such use, and later found a foreigner wrote blog, Speak more clearly.

Abstract classes that use only pure virtual functions do not need to be exported because of the virtual table of pure virtual functions. Here is an example drawn from a foreigner's bkig.

The pure virtual function class is defined as follows:

[CPP]View PlainCopy
  1. The abstract interface for Xyz object.
  2. No extra specifiers required.
  3. struct IXYZ
  4. {
  5. virtual int Foo (int n) = 0;
  6. virtual void Release () = 0;
  7. };
  8. Factory function that creates instances of the Xyz object.
  9. extern "C" Xyzapi ixyz* apientry getxyz ();

The code for using the DLL is as follows:

[CPP]View PlainCopy
    1. #include "XyzLibrary.h"
    2. ...
    3. ixyz* pxyz =:: getxyz ();
    4. if (PXYZ)
    5. {
    6. Pxyz->foo (42);
    7. Pxyz->release ();
    8. PXYZ = NULL;
    9. }

The example exports a method to create the Ixyz object, but does not export the Ixyz object, only the pure virtual function in the Ixyz class. How is this implemented? All I know is that the classes in the DLL need to be exported, the exported symbols will be placed in the export symbol table, when the link to locate the address of the function according to these symbols, the IXYZ class does not declare the export, of course, the function in the class will not be generated in the export symbol table, then how to locate the address of the function? The following diagram in the original text gives a very clear explanation:

The pseudo-code part of the figure explains the function's calling procedure, which is to locate the function through a virtual table. Since the definition of a pure virtual function of the abstract class, such a class after compiling a pure virtual table, you can use this pure virtual table to make function calls, so the first step in using a DLL in this way is to take only pure virtual function abstract class, or interface.
For more information, see below:

First, the simple way to export the class

This is a relatively simple and inappropriate approach that is not recommended.

You can implement an export class only if you want to add __declspec (dllexport) to the exported class. Object space or in the consumer's module, the DLL provides only the function code in the class. The disadvantage is that the user needs to know the implementation of the entire class, including the base class, the member object in the class, that is, all the things related to the exported class, the user must know. As you can see from Dependency Walker, this time the DLL is exporting functions that are related to classes: constructors, assignment operators, destructors, other functions, which are functions that the consumer might use.

This way of exporting a class, in addition to exporting too many things, the user relies too much on the implementation of the class, there are other problems: you must ensure that the same compiler is used. The essence of the exported class is to export the function in the class, because the syntax of the direct export of the class, not the function of the invocation, renaming to set, resulting in the resulting DLL is not universal.

Section code (DLL header file):

2011.10.6//cswuyg//dll Export class, a poor method #pragma once#ifdef naiveapproach_exports#define Naiveapproach_api __declspec ( dllexport) #else # define NAIVEAPPROACH_API __declspec (dllimport) #endif//base class must also be exported, otherwise warning: class  Naiveapproach_api Cbase{public:    void Test ();p rivate:    int m_j;};/ /You must also export class Naiveapproach_api cdate{public:    void Test2 ();p rivate:    int m_k;}; Class Naiveapproach_api Cnaiveapproach:public cbase{public:    cnaiveapproach (int i = 0);    Todo:add your methods here.    void Func ();p rivate:    int m_iwuyg;    CDate m_dobj;};

The demo code is shown in the Attachment Naiveapproach section.

Second, the better way to export the class

This is a more appropriate approach, similar to COM.

The structure is this: the export class is a derived class derived from an abstract class-all pure virtual functions. The user needs to know the structure of this abstract class. A DLL needs to provide at least one interface for getting a pointer to a class object. The user and the DLL provider share an abstract class header file, the user relies on the DLL is very few things, only need to know the interface of the abstract class, and get the object pointer of the export function, object memory space of the application is done in the DLL module, the release is also done in the DLL module, finally remember to call the function to release the object.

This approach is better, generic, and the resulting DLL has no specific environment limitations. The virtual function of the C + + class is used. It is generally used in this way. Apart from the benefits of DLL-derived classes, the use of interfaces with the implementation of separation, can make the structure of the project clearer, users only need to know the interface, and do not need to know the implementation.

Part of the code:

(1) DLL header file:

2011.10.6//cswuyg//dll Export class//dll header file that is shared with its consumer #pragma  once#ifdef matureapproach_exports#define matureapproach_ API __declspec (dllexport) #else # define MATUREAPPROACH_API __declspec (dllimport) #endifclass iexport{public:    virtual void Hi () = 0;    virtual void Test () = 0;    virtual void Release () = 0;}; extern "C" Matureapproach_api iexport* _stdcall createexportobj (); extern "C" Matureapproach_api void _stdcall Destroyexportobj (iexport* pexport);

(2) Export the class header file:

2011.10.6//cswuyg//dll Export class//implementation class #pragma once#include "MatureApproach.h" Class Exportimpl:public Iexport{public:    virtual void Hi ();    virtual void Test ();    virtual void Release ();    ~exportimpl ();p rivate:};

The demo code is shown in the Attachment Matureapproach section.

Iii. Summary

The export class is relatively simple, and it is easy to confuse the concept of a summary has been said. Essentially, there is no difference from the derived function. Using VS2005 Auto-generated code can save a lot of effort, and it's much easier to write your own hands than do the exercises you did before. Be aware of the engineering settings and be familiar with their functions to speed up programming.

Demo Code attachment:

Http://files.cnblogs.com/cswuyg/%E7%BC%96%E5%86%99DLL%E6%89%80%E5%AD%A6%E6%89%80%E6%80%9D (2) (%e5%af%bc%e5%87% BA%E7%B1%BB). rar

Resources:

Http://www.codeproject.com/KB/cpp/howto_export_cpp_classes.aspx

What you can learn from writing DLLs (1)--exporting functions

2010.8.31~2010.9.1 Summary

2011.9.28~30 Finishing

Candle Autumn

There are two ways to use dynamic-link libraries, one for explicit invocation. One is an implicit invocation.

(1) Explicit invocation: Use LoadLibrary to load a dynamic-link library and use GetProcAddress to get a function address.

(2) Implicit invocation: You can use #pragma comment (lib, "XX.lib"), or you can directly add XX.lib to the project.

DLL authoring

When writing DLLs, there is an important problem to solve, that is, the function rename--name-mangling. There are two kinds of solutions, one is directly in the code to solve the use of extent "C", _declspec (dllexport), #pragma comment (linker, "/export:[exports name]=[mangling Name ], the other is a def file.

(1) When writing DLLs, why there is extern "C"

Cause: The renaming rules for C and C + + are not the same. This renaming is called "name-mangling" (name decoration or name adaptation, identifier renaming, some people translated as "name shredding", this translation seems a little confusing)

It is said that the C + + standard does not stipulate the name-mangling scheme, so different compilers use different, for example: Borland C + + Mircrosoft C + + is different, And maybe different versions of the compiler their name-mangling rules are also different. In this case, the target files are compiled by different compilers. obj is not universal, because the same function, using different name-mangling, will have different names in the obj file. If the function renaming rules in the DLL are inconsistent with the renaming rules used by the user of the DLL, then this function will not be found.

The C standard stipulates the specification of C language Name-mangling (Lin Rui's book has said so). This makes it possible for any compiler that supports the C language to compile the obj file to be shared and linked to an executable file. This is a standard, and if the DLL and its users adopt such a convention, then it is possible to resolve the error caused by inconsistent function renaming rules.

In addition to the differences between C + + and C, the difference between the compiler and the name of the symbol, consider the name mangling caused by the calling convention. such as the extern "C" __stdcall call method will be added to the original function name to write the symbol of the parameter, while the extern "C" __cdecl will not append additional symbols.

A function in a DLL is indexed as a function name or function number when it is invoked. This means that DLL files generated by the Name-mangling method of C + + with a compiler may not be generic. Because their function names are renamed differently. In order to make the DLL common, often use C's name-mangling way, that is, each export function is declared as extern "C", and the use of _stdcall calling convention, and then also need to rename the exported function, in order to export the non-decorated function name.

Note that the role of extern "C" is to solve the problem of function symbol name, which is required for both the producer of the dynamic link library and the user of the dynamic link library.

The explicit loading of a dynamic-link library is through the GetProcAddress function, which obtains the function address according to the dynamic link library handle and the function name. Because GetProcAddress is only operating system-related, may operate a variety of compiler-generated DLLs, its parameters in the function name is the full function name, without any modification, so it is generally necessary to ensure that the DLL ' function name is the original function name. In two steps: one, if the export function uses the extern "C" _cdecl, then there is no need to rename, this time the name of the DLL is the original name, if the use of extern "C" _stdcall, when the function name in the DLL is decorated, you need to rename. There are two ways to rename, either use the *.def file, modify it outside the file, or use #pragma to give the function alias in the code.

(2) The role of _declspec (dllexport) and _declspec (dllimport)

_declspec also has additional uses, which are discussed only with DLL-related uses. Just like the keywords in parentheses, export and import. _declspec (dllexport) is used on DLLs to illustrate that this is an exported function. _declspec (dllimport) is used in the program that invokes the DLL to illustrate that this is a function imported from a DLL.

_declspec (dllexport) is necessary because the DLL must state that the function is to be used for export. But in a different way, you can use DEF files to describe which functions are used for export, as well as the number of functions inside the def file.

The use of _declspec (dllimport) is not necessary, but it is advisable to do so. Because if you do not use _declspec (dllimport) to indicate that the function is imported from a DLL, then the compiler does not know where this function is, the generated EXE will have a call xx instruction, this xx is a constant address, XX address is a jmp DWORD PTR[XXXX], jumps to the function body, obviously so that there is no reason for an intermediate jump. If _declspec (dllimport) is used to illustrate, then the call DWORD Ptr[xxx] is generated directly, so there is no extra jump. (Refer to "Encryption and decryption" in the third edition of Page 279)

(3) Impact of __stdcall

This is how a function is called. By default, the VC uses __cdecl function call mode, if the resulting DLL will only be used for C + + programs, then there is no need to define the __stdcall call method, if you want to WIN32 assembly use (or other __stdcall call way of the program), Then you can use __stdcall. This may not be important because you can set the rules for a function call when you call a function. Like VC can be set to call the function, so it is convenient to use Win32 assembly generated DLL. But __stdcall this calling convention will be name-mangling, so I think VC default calling convention is simpler. However, if you have to __stdcall the calling convention, and the function name is not decorated, you can use the *.def file, or give the function an alias in #pragma way in the code (this way you need to know what the modified function name is).

Example:

extern "C" __declspec (dllexport) bool __stdcall Cswuyg ();

extern "C" __declspec (dllimport) bool __stdcall cswuyg ();

• #pragma comment (linker, "/export:[email protected]")

(4) Purpose of the *.def file

Specifies the export function and tells the compiler not to use the decorated function name as the exported function name, but to export the function with the specified function name (such as a function func, so that the function name is still func after the compiler is processed). This avoids link errors due to the unique handling of the Microsoft VC + + compiler.

That is, the use of DEF files, it does not require the extern "C", you can also do not need __declspec (dllexport) (However, DLL manufacturers in addition to provide a DLL, but also to provide a header file, need to add this extern "C" in the header file and calling conventions, because the user needs to follow the same rules as the manufacturer, unless the user and the manufacturer use the same compiler and have no special requirements for the calling convention.

Example def file format:

LIBRARY XX (DLL name this is not required, but must be guaranteed to be the same as the generated DLL name)

Exports

[function name] @ [function ordinal]

After writing, add to the VC project, it is OK.

Also, note that if you want to use __stdcall, you must use the __stdcall in your code, because the *.def file is only responsible for modifying the function name and is not responsible for calling the Convention.

That is, the Def file is just the function name, regardless of how the function balances the stack.

If the *.def file is added to the project, the link does not automatically add it in. Then you can do this:

Manually add in Link:

1) The project Propertiesàconfiguration Propertiesàlinkeràcommand Lineà in the "Additional options" add:/def:[full file name].def

2) The project propertiesàconfiguration propertiesàlinkeràinputàmodule Definition file plus [full file name].def

Note that even with the name decoration of C, the resulting function name may be decorated. For example, in the VC, _stdcall call method, the function name will be decorated, preceded by ' _ ', followed by parameters related to other things. Therefore, it is very important to use the *.def file to name the function.

(5), DllMain function

Each dynamic link library will have a DllMain function. If the DllMain function is not defined at the time of programming, then the compiler will add it to you.

DllMain function Format:

BOOL apientry DllMain (HANDLE hmodule,

DWORD Ul_reason_for_call,

LPVOID lpreserved

)

{

Switch (Ul_reason_for_call)

{

Case Dll_process_attach:

printf ("\nprocess Attach of DLL");

Break

Case Dll_thread_attach:

printf ("\nthread Attach of DLL");

Break

Case Dll_thread_detach:

printf ("\nthread Detach of DLL");

Break

Case Dll_process_detach:

printf ("\nprocess Detach of DLL");

Break

}

return TRUE;

}

(6), many have not learned, such as: Export class, export variables, DLLs more advanced applications. At present, we should understand the basic knowledge. Later on.

2011-8-14 Supplement

Writing a DLL you can use a. def file to name the exported function name.

1, the necessity of dynamically loading DLLs, renaming (*.DEF)?

Because the exported function uses the __stdcall call method whenever possible. In the case of __stdcall, the function name is decorated either by name mangling of C or by the name mangling of C + +. Therefore, after using the __stdcall invocation method, the function name must be renamed using the *.def file, or you cannot use GetProcAddress () to get the function pointer through the function name.

2, when the implicit call, the header file to pay attention to the place?

Because using static loading, a header file is required to declare the function in the DLL to be used, if __stdcall or extern "C" is specified in the declaration, then when the function is called, the compiler will go through the function name after name mangling. lib to find this function, *. The content in def does not work on the name of the function in the *.lib, and the function renaming in the *.def file is only useful for DLLs . This has the Lib and DLL in the function name inconsistent problem, but does not have an impact, DLL manufacturers and users are using a consistent function declaration.

3, so in the end should not use __stdcall it?

I see some of the code is not using __stdcall. If you do not use __stdcall, use the default calling convention _cdecl and have extern "C". Then the VC will not be any modification. In this way, the function name in the generated DLL is the original function name. You can also not use the. def file.

There are also some requirements that must be used for __stdcall, such as COM-related things, system callback functions. Specifically see if there is any need.

4. How do I write the exported function aliases?

You can write an alias to the function name in the. def file.

For example:

Exports

Cswuygtest (alias) = [email protected] (function to export)

Or:

#pragma COMMENT (linker, "/export:[alias" =[namemangling name] ")

This makes it possible to modify the alias arbitrarily, without the error of not finding the symbol.

5. Do not use *.def files?

If you adopt the VC default calling convention, you can use the *.def file, if you want to adopt the __stdcall calling convention, and do not want the function name to be decorated, then use the *.def file bar, another way to write in the code is not easy to rename.

6, under what circumstances (not) need to consider the problem of function renaming?

1), implicit invocation (via Lib)

If the manufacturer of the DLL and the user of the DLL use the same language, the same programming environment, then you do not need to consider function renaming. When the user calls the function, the function name after the name mangling can be found in Lib.

If the manufacturer of the DLL is using a different language than the DLL, or a different compiler, then you need to consider renaming.

2), display call (via Getprocessaddress)

This is definitely a function that must be considered for renaming.

7. Summary

In general, when writing a DLL, write a header file that declares the function's namemingling, calling convention (mainly for implicit invocation). Write a *.def file to rename the function (mainly for explicit invocation). Provide *. Dll\*.lib\*.h to the user of the DLL, so whether the implicit invocation, or explicit invocation, can be done conveniently.

Report:

An example of a simple DLL export function: Http://files.cnblogs.com/cswuyg/%E7%BC%96%E5%86%99DLL%E6%89%80%E5%AD%A6%E6%89%80%E6%80%9D.rar

Learning materials:

Http://www.cnblogs.com/dongzhiquan/archive/2009/08/04/1994764.html

Http://topic.csdn.net/u/20081126/14/70ac75b3-6e79-4c48-b9fe-918dce147484.html


C + + DLL export class knowledge Daquan

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.