• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            把握命運,追逐夢想

            對自己所做的事要有興趣,同時還要能夠堅持不懈

            統計

            留言簿(1)

            閱讀排行榜

            評論排行榜

            一個C++DLL的簡單例子

             

            // PureApp.cpp : 定義應用程序的入口點。
            //

            // Windows 頭文件:
            #include <windows.h>

            // C 運行時頭文件
            #include <stdlib.h>
            #include 
            <malloc.h>
            #include 
            <memory.h>
            #include 
            <tchar.h>

                #include "resource.h"

            #include 
            "PureApp.h"
            #include 
            "PureDll.h"

            #define MAX_LOADSTRING 100

            // 全局變量:
            HINSTANCE hInst;                                // 當前實例
            TCHAR szTitle[MAX_LOADSTRING];                    // 標題欄文本
            TCHAR szWindowClass[MAX_LOADSTRING];            // 主窗口類名

            // 此代碼模塊中包含的函數的前向聲明:
            ATOM                MyRegisterClass(HINSTANCE hInstance);
            BOOL                InitInstance(HINSTANCE, 
            int);
            LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
            INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);

            int APIENTRY _tWinMain(HINSTANCE hInstance,
                                 HINSTANCE hPrevInstance,
                                 LPTSTR    lpCmdLine,
                                 
            int       nCmdShow)
            {
                UNREFERENCED_PARAMETER(hPrevInstance);
                UNREFERENCED_PARAMETER(lpCmdLine);

                 
            // TODO: 在此放置代碼。
                MSG msg;
                HACCEL hAccelTable;

                
            // 初始化全局字符串
                LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
                LoadString(hInstance, IDC_PUREAPP, szWindowClass, MAX_LOADSTRING);
                MyRegisterClass(hInstance);

                
            // 執行應用程序初始化:
                if (!InitInstance (hInstance, nCmdShow))
                
            {
                    
            return FALSE;
                }


                hAccelTable 
            = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_PUREAPP));

                
            // 主消息循環:
                while (GetMessage(&msg, NULL, 00))
                
            {
                    
            if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
                    
            {
                        TranslateMessage(
            &msg);
                        DispatchMessage(
            &msg);
                    }

                }


                
            return (int) msg.wParam;
            }




            //
            //  函數: MyRegisterClass()
            //
            //  目的: 注冊窗口類。
            //
            //  注釋:
            //
            //    僅當希望
            //    此代碼與添加到 Windows 95 中的“RegisterClassEx”
            //    函數之前的 Win32 系統兼容時,才需要此函數及其用法。調用此函數十分重要,
            //    這樣應用程序就可以獲得關聯的
            //    “格式正確的”小圖標。
            //
            ATOM MyRegisterClass(HINSTANCE hInstance)
            {
                WNDCLASSEX wcex;

                wcex.cbSize 
            = sizeof(WNDCLASSEX);

                wcex.style            
            = CS_HREDRAW | CS_VREDRAW;
                wcex.lpfnWndProc    
            = WndProc;
                wcex.cbClsExtra        
            = 0;
                wcex.cbWndExtra        
            = 0;
                wcex.hInstance        
            = hInstance;
                wcex.hIcon            
            = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_PUREAPP));
                wcex.hCursor        
            = LoadCursor(NULL, IDC_ARROW);
                wcex.hbrBackground    
            = (HBRUSH)(COLOR_WINDOW+1);
                wcex.lpszMenuName    
            = MAKEINTRESOURCE(IDC_PUREAPP);
                wcex.lpszClassName    
            = szWindowClass;
                wcex.hIconSm        
            = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

                
            return RegisterClassEx(&wcex);
            }


            //
            //   函數: InitInstance(HINSTANCE, int)
            //
            //   目的: 保存實例句柄并創建主窗口
            //
            //   注釋:
            //
            //        在此函數中,我們在全局變量中保存實例句柄并
            //        創建和顯示主程序窗口。
            //
            BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
            {
               HWND hWnd;

               hInst 
            = hInstance; // 將實例句柄存儲在全局變量中

               hWnd 
            = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
                  CW_USEDEFAULT, 
            0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

               
            if (!hWnd)
               
            {
                  
            return FALSE;
               }


               ShowWindow(hWnd, nCmdShow);
               UpdateWindow(hWnd);

               
            return TRUE;
            }


            //
            //  函數: WndProc(HWND, UINT, WPARAM, LPARAM)
            //
            //  目的: 處理主窗口的消息。
            //
            //  WM_COMMAND    - 處理應用程序菜單
            //  WM_PAINT    - 繪制主窗口
            //  WM_DESTROY    - 發送退出消息并返回
            //
            //
            LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
            {
                
            int wmId, wmEvent;
                PAINTSTRUCT ps;
                HDC hdc;
                CPureDll pureDll(
            4);
                pureDll.setValue(
            3);

                
            switch (message)
                
            {
                
            case WM_COMMAND:
                    wmId    
            = LOWORD(wParam);
                    wmEvent 
            = HIWORD(wParam);
                    
            // 分析菜單選擇:
                    switch (wmId)
                    
            {
                    
            case IDM_ABOUT:
                        DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
                        
            break;
                    
            case IDM_EXIT:
                        DestroyWindow(hWnd);
                        
            break;
                    
            default:
                        
            return DefWindowProc(hWnd, message, wParam, lParam);
                    }

                    
            break;
                
            case WM_PAINT:
                    hdc 
            = BeginPaint(hWnd, &ps);
                    
            // TODO: 在此添加任意繪圖代碼
                    TCHAR buf[50];
                    swprintf(buf,L
            "DLL中的全局整數nPureDll的值為%d",nPureDll);
                    TextOut(hdc,
            0,0,buf,wcslen(buf));
                    swprintf(buf,L
            "DLL中的全局類對象g_pureDll的成員值分別為%d,%d,%d,%d,%d",g_pureDll.m_num,
                        g_pureDll.m_p[
            0],g_pureDll.m_p[1],g_pureDll.m_p[2],g_pureDll.m_p[3] );
                    TextOut(hdc,
            0,20,buf,wcslen(buf));
                    swprintf(buf,L
            "用DLL的類定義的對象pureDll的成員值分別為%d,%d,%d,%d,%d",pureDll.m_num,
                        pureDll.m_p[
            0],pureDll.m_p[1],pureDll.m_p[2],pureDll.m_p[3] );
                    TextOut(hdc,
            0,40,buf,wcslen(buf));
                    EndPaint(hWnd, 
            &ps);
                    
            break;
                
            case WM_DESTROY:
                    PostQuitMessage(
            0);
                    
            break;
                
            default:
                    
            return DefWindowProc(hWnd, message, wParam, lParam);
                }

                
            return 0;
            }


            // “關于”框的消息處理程序。
            INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
            {
                UNREFERENCED_PARAMETER(lParam);
                
            switch (message)
                
            {
                
            case WM_INITDIALOG:
                    
            return (INT_PTR)TRUE;

                
            case WM_COMMAND:
                    
            if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
                    
            {
                        EndDialog(hDlg, LOWORD(wParam));
                        
            return (INT_PTR)TRUE;
                    }

                    
            break;
                }

                
            return (INT_PTR)FALSE;
            }

            //這個文件與DLL用的頭文件稍微有些不同,后面提到

            // 下列 ifdef 塊是創建使從 DLL 導出更簡單的
            // 宏的標準方法。此 DLL 中的所有文件都是用命令行上定義的 PUREDLL_EXPORTS
            // 符號編譯的。在使用此 DLL 的
            // 任何其他項目上不應定義此符號。這樣,源文件中包含此文件的任何其他項目都會將
            // PUREDLL_API 函數視為是從 DLL 導入的,而此 DLL 則將用此宏定義的
            // 符號視為是被導出的。

            #ifdef __cplusplus
            extern "C"
            {
            #endif
            #ifdef PUREDLL_EXPORTS
            #define PUREDLL_API __declspec(dllexport)
            #else
            #define PUREDLL_API __declspec(dllimport)
            #endif

                
            // 此類是從 PureDll.dll 導出的
                class PUREDLL_API CPureDll {
                
            public:
                    CPureDll(
            int num);
                    
            // TODO: 在此添加您的方法。

                    
            ~CPureDll(void);
                    
            void setValue(int value);
                
            public:
                    
            int m_num;
                    
            int *m_p;
                }
            ;

                
            extern PUREDLL_API int nPureDll;

                
            extern PUREDLL_API CPureDll g_pureDll;

                PUREDLL_API 
            int fnPureDll(void);

            #ifdef __cplusplus
            }

            #endif

            // dllmain.cpp : 定義 DLL 應用程序的入口點。
            #include "windows.h"

            BOOL APIENTRY DllMain( HMODULE hModule,
                                   DWORD  ul_reason_for_call,
                                   LPVOID lpReserved
                                 )
            {
                
            switch (ul_reason_for_call)
                
            {
                
            case DLL_PROCESS_ATTACH:
                
            case DLL_THREAD_ATTACH:
                
            case DLL_THREAD_DETACH:
                
            case DLL_PROCESS_DETACH:
                    
            break;
                }

                
            return TRUE;
            }

            // PureDll.cpp : 定義 DLL 應用程序的導出函數。
            //

            #include 
            "windows.h"
            #include 
            "PureDll.h"


            // 這是導出變量的一個示例
            PUREDLL_API int nPureDll=10;

            PUREDLL_API CPureDll g_pureDll(
            4);

            // 這是導出函數的一個示例。
            PUREDLL_API int fnPureDll(void)
            {
                
            return 10;
            }


            // 這是已導出類的構造函數。
            // 有關類定義的信息,請參閱 PureDll.h
            CPureDll::CPureDll(int num)
            {
                
            this->m_num = num;
                
            this->m_p = new int[num];
                memset(m_p,
            0,m_num*sizeof(int));
            }


            CPureDll::
            ~CPureDll()
            {
                delete m_p;
            }


            void CPureDll::setValue(int value)
            {
                
            for(int i = 0; i <m_num; i++)
                
            {
                    
            this->m_p[i] = value;
                }

            }

            //這個頭文件與App中用的稍有不同

            // 下列 ifdef 塊是創建使從 DLL 導出更簡單的
            // 宏的標準方法。此 DLL 中的所有文件都是用命令行上定義的 PUREDLL_EXPORTS
            // 符號編譯的。在使用此 DLL 的
            // 任何其他項目上不應定義此符號。這樣,源文件中包含此文件的任何其他項目都會將
            // PUREDLL_API 函數視為是從 DLL 導入的,而此 DLL 則將用此宏定義的
            // 符號視為是被導出的。

            #ifdef __cplusplus
            extern "C"
            {
            #endif
            #ifdef PUREDLL_EXPORTS
            #define PUREDLL_API __declspec(dllexport)
            #else
            #define PUREDLL_API __declspec(dllimport)
            #endif

                
            // 此類是從 PureDll.dll 導出的
                class PUREDLL_API CPureDll {
                
            public:
                    CPureDll(
            int num);
                    
            // TODO: 在此添加您的方法。

                    
            ~CPureDll(void);
                    
            void setValue(int value);
                
            private:
                    
            int m_num;
                    
            int *m_p;
                }
            ;

                
            extern PUREDLL_API int nPureDll;

                
            extern PUREDLL_API CPureDll g_pureDll;

                PUREDLL_API 
            int fnPureDll(void);

            #ifdef __cplusplus
            }

            #endif



            比較一下上面的兩個PureDll.h頭文件就會發現,他們的成員的保護級別不同,App中的是public,而Dll中的是private,但是我在vc2008上卻完成了這個工程并正常運行,我剛開始以為是extern C把C++修飾符號簡化導致不能識別保護級別,但是我把extern C注釋之后,仍然沒有問題,后來找資料發現修飾符沒有關于保護級別的內容,所以就是說vc的保護級別完全是在編譯階段的,和鏈接階段一點關系都沒有。
            當然兩個不一樣的同名頭文件,這樣做是錯的,這里就是發現了這個問題,所以提出來而已。
            上面說的這個問題其實就是編譯階段和鏈接階段是分開的,還是上面的例子,其實我們不需要導出整個類的,只需要在要導出的成員函數前面加上導出符號即可,因為使用dumpbin就會看到,導出的符號里一點類聲明的影子都沒有,而我們在調用DLL的代碼中定義類對象,其實是編譯器根據頭文件中的類定義體來完成對象的生成,看VC中反匯編代碼會看到這個過程,而DLL中是把類成員函數當成普通函數導出的,只不過加了些特殊的標記而已,編譯器在編譯類成員函數的聲明時也是產生這樣的特殊符號,所以其實調用過程就像普通函數一樣。
            還有就是變量的導出問題,一般是在頭文件中用extern,然后再cpp中定義這個變量,這個extern符號只能在obj文件之間使用,如果要從dll中導出需要在extern 的前面或者后面使用_declspec(dllexport),在導入頭文件中在extern前面或者后面添加_declspec(dllimport)。否則導出符號中不存在這個變量,可以使用dumpbin察看到這個情況。

            posted on 2009-08-03 15:41 把握命運 閱讀(2010) 評論(0)  編輯 收藏 引用

            久久亚洲精品无码观看不卡| 国产产无码乱码精品久久鸭| 中文字幕乱码人妻无码久久| 九九久久精品无码专区| 996久久国产精品线观看| 久久精品国产亚洲AV香蕉| 久久亚洲国产精品123区| 久久国产精品无码网站| 伊人色综合久久| 国内精品免费久久影院| 91久久香蕉国产熟女线看| 久久成人国产精品二三区| 久久国产精品成人免费| 久久青草国产手机看片福利盒子| 久久AV高清无码| 久久精品一区二区国产| 91性高湖久久久久| 久久精品无码av| 热久久视久久精品18| 18禁黄久久久AAA片| 亚洲精品国精品久久99热一| 欧洲人妻丰满av无码久久不卡| 无码人妻少妇久久中文字幕蜜桃| 久久综合亚洲欧美成人| a级成人毛片久久| 狠狠色丁香婷婷综合久久来来去 | 亚洲午夜福利精品久久| 亚洲国产成人精品久久久国产成人一区二区三区综 | 99国产欧美久久久精品蜜芽| 99久久精品国内| 久久99热这里只有精品国产| 色妞色综合久久夜夜| 国产精品女同久久久久电影院| 色综合合久久天天综合绕视看| 精品久久久久中文字| 久久精品国产亚洲αv忘忧草| 精品精品国产自在久久高清| 青青草原综合久久大伊人导航| 亚洲AV无一区二区三区久久| 中文字幕久久欲求不满| 一本一本久久a久久精品综合麻豆|