In-depth drafting DLL (introduction function export, class export, fishing DLL, different language mixing programming methods, plug-ins) implementation method)
All code is tested, if you have any questions, you can leave a message. There are two simple DLL function calls: 1. Explicit call 2. Implicit call. As of the following example
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx // dlltest.cpp: Dll write // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx # include
extern "C" __declspec (dllexport) int Add (int n1, int n2); BOOL APIENTRY DllMain (HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {if (ul_reason_for_call == DLL_PROCESS_ATTACH) {// TRACE0 ( "DLL Initializing / n! ");} else if (ul_reason_for_call = DLL_PROCESS_DETACH) {// trace0 (" DLL Terminating! / N ");} Return True;
__DECLSPEC (DLLEXPORT) Add (int N1, int N2) {char sztxt [1024]; sprintf (sztxt, "% D % D =% D" D ", N1, N2, N1 N2); MessageBox (0, sztxt," DLL RESPOND here: ", 0); return 1;}
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx // usedll.cpp: Dll call test // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx # include
// # Define USSTATELIB
// Implicit link mode: #ifdef useestatelib #pragma Comment (lib, "lib // dlltest.lib") EXTERN "C" __DECLSPEC (DLLIMPORT) INT Add (INT N1, INT N2); # ENDIF
int APIENTRY WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {# ifndef USESTATELIB // explicit invocation: HINSTANCE hIns = LoadLibrary ( "dlltest.dll"); if {MessageBox (0, "(hIns!) COULDN't Find Dlltest.dll "," Error: ", 0); Return 0;} typef INT (DLL_ADD) (INT, INT); DLL_ADD * Testit = (DLL_ADD *) GetProcAddress (Hins," Add "); if (Testit) {(* testit) (1, 2);} else {MessageBox (0, "couldn't Find ADD from dlltest.dll", "Error:", 0); return 0;} freeelibrary (GetModuleHandle) dlltest.dll ")); # else // implicit link mode: int nres = Add (1, 2); # endifreturn 0;} // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx // II. Export Category // Note that the CTEST class should be defined in the file header, and DLlexPort is best to use macro judge definition, // and only test here. // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx1. DLL generation: // TDLL.CPP: Defines the entry point for the dll application.//
#include "stdafx.h"
Class __Declspec (dllexport) ctest {private: int m_nvalue;
PUBLIC: CTEST (): m_nvalue (0) {} int getValue () const;}; int ctest :: getValue () const {return m_nvalue;}
Bool Apientry Dllmain (Handle Hmodule, DWORD UL_REASON_FOR_CALL, LPVOID LPRESERVED) {Return True;}
2. Call (remember to copy the above-described TDLL.DLL and TDLL.LIB): # pragma comment (lib, "tdll.lib")
Class __declspec (dllimport) ctest {private: int m_nvalue;
PUBLIC: ctest (): m_nvalue (1) {} int getValue () const;
INT Main (int Argc, char * argv []) {
CTest a; int kk = a.getValue ();
Running is correct.
Interesting phenomenon is: When I change the DLLIMPORT error of the application to DLLEXPORT, the program can still be BUILD (not comment #pragma comment (lib, "tdll.lib"), and the runtime results are 1 (for difference At the initial value of the DLL, I put the initial initial 1). Well, this is because the compiler is handling the CTEST of the application, and the compilation does look at the class structure, and the link can also be found in TDLL.LIB in TDLL.LIB, so Build is successful, and since it is running itself CTEST is DLLEXPORT, of course, is running it directly. // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx // three. DLL // 1. See my QQ this horse program: // http://blog.gameres.com/thread.asp?blogid=386&;threadid=13701;threadId=13701// 2. Another The DLL used to press the F3 pop-up DLL box for output DEBUG information, the code is as follows: // Create a Win32DLL with VC, select the Resource under Insert in the menu, insert a Dialog Press Ctrl S in the store, and write the contents as follows: / / Logdll.h content: #ifdef logdll_exports # define logdll_api __declspec (dllexport) # Else # define logdll_api __declspec (dllimport) #ENDIF
Extern "C" logdll_api void LG (const char * sztxt);
// logdll.cpp content: // # include
// global data: #pragma comment (linker, "section: Shared, rws") #pragma data_seg ( "Shared") HHOOK g_hhook = NULL; HINSTANCE g_hInstance = NULL; HWND g_pLogDlg = NULL; BOOL g_bShowDlg = FALSE; #pragma data_seg ()
/ / -------------------------------------------------------------------------------------------- ------------------------ void init (); void finish (); bool showlogdlg (); BOOL Showlogdlg (); void installhook (); void Uninstallhook ();
LResult Callback KeyboardProc (int, wparam, lparam); int_ptr callback LGDLGPROC (HWND, UINT, WPARAM, LPARAM)
/ / -------------------------------------------------------------------------------------------- ------------------------ / ** / BOOL CREATELOGDLG () {IF (g_plogdlg) Return True;
IF (false == g_hinstance) Return False; g_plogdlg = createdialog (g_hinstance, makeintresource (idd_dialog1), null, (dlgproc) lgdlgproc); return true;} // ------------- -------------------------------------------------- ----- / ** / bool showlogdlg () {if (null == g_plogdlg) {if (false == Createlogdlg ()) Return False;} Return ShowWindow (g_plogdlg, (g_bshowdlg =! G_bshowdlg)? SW_SHOW : Sw_hide);} // ------------------------------------------- ----------------------------- / ** / void installhook () {if (g_hhook == null) {g_hhook = setwindowshookex Wh_keyboard, (hookProc) KeyboardProc, g_hinstance, 0);}} // -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------- / ** / void uninstallhook () {ified (g_hhook ) {UNHOOKWINDOWSHOKEX (g_hhook); g_hhook = null;}}
/ / -------------------------------------------------------------------------------------------- ----------------------- / ** / logdll_api void lg (const char * sztxt) {// Here set the text info to your dialog's text ctrl } void init () {installhook ();} void Finish () {uninstallhook (); if (g_plogdlg) {destroyWindow (g_plogdlg); g_plogdlg = null;}} // -------------- -------------------------------------------------- ---------- / ** / BOOL APIENTRY DllMain (HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {g_hInstance = (HINSTANCE) hModule; switch (ul_reason_for_call) {case DLL_PROCESS_ATTACH: Init (); break; case DLL_THREAD_ATTACH: INIT (); Break; Case DLL_THREAD_DETACH: FINISH (); Break; Case DLL_Process_Detach: finish (); Break;} Return True;} // ----------------- -------------------------------------------------- ----- / ** / Lresult Callback KeyboardProc (Int Ncode, WPARAM WPARAM, LRESULT RES = CallNextHookex (g_hhook, ncode, wparam, lparam); if ((LParam & (1 << 31)) && (wparam == vk_f3) && (ncode == hc_action)) {showlogdlg ();} return } // ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ -------------------------- / ** / int_ptr Callback LGDLGPROC (HWND HDLG, UINT MSG, WPARAM WPARAM, LPARAM LPARAM) {Switch (MSG ) {Case WM_INITDIALOG: RETURN TRUE; CASE WM_COMMAND: Switch (WPARAM) {CASE IDCANCEL: CASE IDOK: EndDialog (HDLG, TRUE); g_bshowdlg = false; return true;} Break;
Case WM_DESTROY: BREAK;
Return false;}
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx // four. Different language hybrid programming methods // The title is too exaggerated, here is just written in a language to use another language. For example: Write a DLL in the VC and calls in VB. This has a dream example in the article I reprint, I will not say more, see: (Quote the "library" of others, and write a lot less "code", huh, http://blog.gameres.com /thread.asp?BlogID=386&;threadid=13945//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx// V. Plug-in DLL related write // (I wrote the following example to explain how the 3DMAX export plugin is written and implemented, // source code is not explained) // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxXxxxxxxxxxxx us here our program I use app.h and app.cpp. And someone written in PlugTest.h with plugtest.cpp. 1. Write our program first (create with the establishment of a normal Win32 program method)
// app.h header file content: #include
// Define USING_IMPORT by app's project setting that this head file local at #ifdef USING_IMPORT # define THIS_CLASS_EXPORT __declspec (dllimport) # else # define THIS_CLASS_EXPORT __declspec (dllexport) #endif
Class this_class_export test instrument {public: testExport () {}; virtual ~ testExport ()}; virtual int doExport () = 0;
Class this_class_export classdesc {public: virtual hinstance hinstance () = 0; virtual void * create () = 0; // {return new testexport's derive class}};
// app.cpp file content: // # include "app.h" #include
TYPEDEF CLASSDESC * (* pfn_desc) ();
Void TestCall (const char * szname) {hinstance hdll = loadingLibrary (szname); PFN_DESC PPLUGDESC = (PFN_DESC) GetProcAddress (HDLL, "Get_PlugDesc");
ClassDesc * pdesc = (* pPLUGDESC) (); if (pdesc) {TESTEXPORT * PEXP = (TESTEXPORT *) PDESC-> CREATE (); if (pEXP) {PEXP-> doExport ();}}}
int APIENTRY WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {// search all dll: struct _finddata_t c_file; long hFile; / * Find first .c file in current directory * / if ((hFile = _findfirst ( " * .dll ", & c_file) == -1L) Printf (" no * .dll files in current directory! / n "); else {testcall (c_file.name); / * Find the rest of the .c files * / While (_findnext (hfindnext (hfindnext (hfile, & c_file) == 0) {TestCall (c_file.name);} _findclose (hfile);
Return 0;}
Next, write a plugin to test: You can create a DLL content in the Create method of normal Win32 DLL in the VC: // plugtest.cpp content // # include
/ / # Pragma Comment (lib, "app.lib")
Hinstance G_HINSTANCE;
// eXample: // notic: must not define using_import (Because this example Using for client) Class DLL_PLUG: Public TESTEXPORT {INT DoExport () {MessageBox (0, "Test OK", "OK", 0); Return 1; }}; class test_plusclassdesdesc: public classdesc {hinstance hinstance () {return g_hinstance;} void * create () {return new dll_plug;}}
Static Test_plusclassdesc Test_plusdesc;
Extern "c" this_class_export classdesc * get_plugdesc () {return & test_plusdesc;}
Bool Apientry Dllmain (Handle Hmodule, DWORD UL_REASON_FOR_CALL, LPVOID LPRESERVED) {g_hinstance = (hinstance) hModule; return true;}
[Note:] 1. The function call has a different approach, with the extern "C", the C convention is different, and the specifically reflected in the output symbol, the symbols of general C are the same as the function name. C , with xx @ xxxx (this available DLL Viewing Tools), mainly the difference between the difference parameters (in order to handle similar overloading, etc.), the related articles can be found in the article: http://blog.gameres. COM / THREAD.ASP? BlogId = 386 &; threadid = 139452. DLL View Tool Recommended: Process Explorer.exe, Dependency Walker.exe is very useful, if your project is often dealing with a bunch of DLL, you know how to use them Isolated the relationship between different DLL projects, I found the reason why the symbols found. Related tools See: http://blog.gameres.com/show.asp?blogid=386&;column=469