DLL
Explicit links have greater flexibility than implicit links some at some time. For example, if you find a DLL at runtime
Unable to find, the program can display an error message and can continue to run. Explicit links are also useful when you want to provide plug-in services for your program.
Explicit links to global C / C functions are very simple. Suppose you want to call a function exportedfn in the DLL, you can export it very simply:
Extern "C" _Declspec (DLLEXPORT)
Void Exportedfn (int Param1, Char * param2);
You must use the Extern "C" link tag, otherwise the C compiler generates a modified function name, which exports the name of the function will no longer be exportedfn, but a name, such as "?" Exportedfn @ Qaex "name. Suppose this function is exported from DLL1.dll, then the client can call this function like this:
HModule hmod = loadingLibrary ("dll1.dll");
Typedef void (* pEXPORTEDFN) (int, char *);
PEXPORTEDFN PFNEF = (PEXPORTEDFN) GetProcadress ("exportedfn");
Pfnef (1, "SomeString");
What should I do if you want to export and explicitly link a group of C member functions? There are two problems here. The first is that the C member function name is modified (even if the specified Extern "C" tag is also like this); the second is that C does not allow the pointer to the member function to other types. These two issues limit explicit links for the C class. The following describes two methods to solve this problem: 1 Method for using virtual functions, this is also a method of COM use; 2 Call directly with GetProcAddress. I will explain this class as an example:
Class A
{
Private:
INT m_nnun;
PUBLIC:
A ();
A (int N);
Virtual ~ a ();
Void setNum (INT N);
Int getnum ();
}
One. Explicit link with virtual function table
This method is the foundation of COM. When we define a set of virtual functions, the compiler creates a virtual function table that places the addresses of the virtual functions in the order of declarations. When a class object is created, its first four bytes are a pointer, pointing to this virtual function table. If we modify a definition to this:
Class A
{
Private:
INT m_nnun;
PUBLIC:
A ();
A (int N);
Virtual ~ a ();
Virtual void setnum (INT N);
Virtual int GetNum ();
}
Then a virtual function table will be created by the compiler, which contains the address of three functions: destructor, setnum, and getnum. The class object is now created in the DLL. Since we want to explicitly link, some global export functions need to call the Operator New to create objects. Because A has two configuration functions, we define two functions createObjectofa () and CreateObjectofa1 (int) and export them. Customers can use class objects like this:
Typedef a * (* pfncreatea1) ();
PFNCREATEA1 PFNCREATEA1 =
(Pfncreatea1) getProcaddress (HMOD, Text ("CreateObjectofa1");
A * a = (PFNCREATEA1) (); A-> setnum (1);
_tprintf (text ("Value of M_nnum IN A% D / N"), A-> GetNum ());
Delete a;
It should be noted that CREATEOBJECTOFA must use Operator New to create an object such that the client can safely call Operator Delete to destroy the object:
Extern "C" __declspec (dllexport) A * CreateObjectofa1 ()
{
Return new a ();
}
The use of this method can make the plugin for your program. Its disadvantage is that the memory of the object must be assigned in the DLL.
two. Explicit links directly using getProcAddress
The key to this method is to convert the FarProc type returned by the getProcAddress function to the pointer to the member function in C . Fortunately, this goal can be easily achieved by C UNIO and template mechanism. What we have to do is only defined the following functions:
Template
DEST force_cast (src src) {
Union {
DEST D;
Src S;
CONVERTOR;
Convertor.s = src;
Return Convertor.d;
}
The above function allows us to convert in any type, which is more effective than ReinterPret_cast. For example, we define a pointer type:
Typedef void (a :: * psetnum) (int);
We can convert the FarProc type pointer FP to PsetNum:
PsetNum PSN = force_cast
After finding the way FarProc is converted into a member function pointer, we must consider how to export the C member function to a more friendly name. This can be implemented by a .def file.
The first step is to find a function name to be protected through the modified function, which can be implemented by viewing the MAP file or assembly code. Then specify a new function name of the export function in the .def file:
Exports
Constructorofa1 = ?? 0a @@ qae @ xz private
Constructorofa2 = ?? 0a @@ qae @ h @ z private
SetNumofa =? Setnum @ a @@ uaexh @ z private
GetNumofa =? Getnum @ a @@ uaehxz private
DESTRUCTOROFA = ?? 1a @@ uae @ xz private
Below is a way to call these member functions:
Typedef void (a :: * pfnconstructorofa1) ();
Typedef void (a :: * pfnconstructorofa2) (int);
Typedef void (a :: * pfndestructorofa) ();
Typedef void (a :: * pfnsetnumofa) (int);
TYPEDEF INT (a :: * pfNGetNumofa) ();
A * a1 = (a *) _ Alloca (SizeOf (a));
Pfnconstructorofa1 pfnconsa =
Force_cast
PFNSETNUMOFA PFNSETNUMA =
Force_cast
(a1 -> * pfnsetnuma) (1);
PfNGETNUMOFA PFNGETNUMA =
Force_cast
_tprintf (text ("Value of M_NNUM IN A% D / N"), (A1 -> * PFNGETNUMA) ());
Pfndestructorofa pfndesta =
Force_cast
(a1 -> * pfndesta) ();
Note that alloca is allocated from the stack from the stack, you can also allocate memory from the heap using Malloc. But you can't use the C New operator, because you can allocate the memory compiler automatically insert the call to the constructor. But we want an explicit link, so this must be avoided. The result produced is that we can only reverse the constructor and the destructive function.