• <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>

            把握命運(yùn),追逐夢想

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

            統(tǒng)計(jì)

            留言簿(1)

            閱讀排行榜

            評論排行榜

            一個C++DLL的簡單例子

             

            // PureApp.cpp : 定義應(yīng)用程序的入口點(diǎn)。
            //

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

            // C 運(yùn)行時頭文件
            #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;                                // 當(dāng)前實(shí)例
            TCHAR szTitle[MAX_LOADSTRING];                    // 標(biāo)題欄文本
            TCHAR szWindowClass[MAX_LOADSTRING];            // 主窗口類名

            // 此代碼模塊中包含的函數(shù)的前向聲明:
            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);

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


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

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

                }


                
            return (int) msg.wParam;
            }




            //
            //  函數(shù): MyRegisterClass()
            //
            //  目的: 注冊窗口類。
            //
            //  注釋:
            //
            //    僅當(dāng)希望
            //    此代碼與添加到 Windows 95 中的“RegisterClassEx”
            //    函數(shù)之前的 Win32 系統(tǒng)兼容時,才需要此函數(shù)及其用法。調(diào)用此函數(shù)十分重要,
            //    這樣應(yīng)用程序就可以獲得關(guān)聯(lián)的
            //    “格式正確的”小圖標(biāo)。
            //
            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);
            }


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

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

               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;
            }


            //
            //  函數(shù): WndProc(HWND, UINT, WPARAM, LPARAM)
            //
            //  目的: 處理主窗口的消息。
            //
            //  WM_COMMAND    - 處理應(yīng)用程序菜單
            //  WM_PAINT    - 繪制主窗口
            //  WM_DESTROY    - 發(fā)送退出消息并返回
            //
            //
            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中的全局整數(shù)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;
            }


            // “關(guān)于”框的消息處理程序。
            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 塊是創(chuàng)建使從 DLL 導(dǎo)出更簡單的
            // 宏的標(biāo)準(zhǔn)方法。此 DLL 中的所有文件都是用命令行上定義的 PUREDLL_EXPORTS
            // 符號編譯的。在使用此 DLL 的
            // 任何其他項(xiàng)目上不應(yīng)定義此符號。這樣,源文件中包含此文件的任何其他項(xiàng)目都會將
            // PUREDLL_API 函數(shù)視為是從 DLL 導(dǎo)入的,而此 DLL 則將用此宏定義的
            // 符號視為是被導(dǎo)出的。

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

                
            // 此類是從 PureDll.dll 導(dǎo)出的
                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 應(yīng)用程序的入口點(diǎn)。
            #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 應(yīng)用程序的導(dǎo)出函數(shù)。
            //

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


            // 這是導(dǎo)出變量的一個示例
            PUREDLL_API int nPureDll=10;

            PUREDLL_API CPureDll g_pureDll(
            4);

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


            // 這是已導(dǎo)出類的構(gòu)造函數(shù)。
            // 有關(guān)類定義的信息,請參閱 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 塊是創(chuàng)建使從 DLL 導(dǎo)出更簡單的
            // 宏的標(biāo)準(zhǔn)方法。此 DLL 中的所有文件都是用命令行上定義的 PUREDLL_EXPORTS
            // 符號編譯的。在使用此 DLL 的
            // 任何其他項(xiàng)目上不應(yīng)定義此符號。這樣,源文件中包含此文件的任何其他項(xiàng)目都會將
            // PUREDLL_API 函數(shù)視為是從 DLL 導(dǎo)入的,而此 DLL 則將用此宏定義的
            // 符號視為是被導(dǎo)出的。

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

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

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


            只有注冊用戶登錄后才能發(fā)表評論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


            伊人色综合久久天天| 天天影视色香欲综合久久| 一本久久精品一区二区| 亚洲天堂久久精品| 久久成人精品视频| 久久水蜜桃亚洲av无码精品麻豆| 久久久这里有精品| 日日狠狠久久偷偷色综合免费 | 99久久精品国产综合一区| 久久综合噜噜激激的五月天| 亚洲中文字幕无码久久综合网 | 色综合久久天天综线观看| 久久噜噜久久久精品66| 久久国产精品免费| 久久综合伊人77777| 青草久久久国产线免观| 亚洲精品视频久久久| 伊人色综合久久天天人守人婷| 亚洲精品高清一二区久久| 伊人久久大香线蕉综合网站| 亚洲人成无码网站久久99热国产| 欧美成a人片免费看久久| 亚洲美日韩Av中文字幕无码久久久妻妇 | 伊人伊成久久人综合网777| 一级做a爰片久久毛片毛片 | 久久人人爽人人爽人人爽| 精品久久久无码人妻中文字幕| 久久久久免费精品国产| 国产亚洲综合久久系列| 国产高潮国产高潮久久久91| 亚洲欧美一级久久精品| 久久久久亚洲av无码专区| 日本免费久久久久久久网站| 久久精品无码专区免费| 一本久久综合亚洲鲁鲁五月天亚洲欧美一区二区 | 伊人久久一区二区三区无码| 伊人久久久AV老熟妇色| 久久国产精品久久国产精品| 久久久久久久久久免免费精品| 久久这里只有精品首页| 久久精品一区二区三区不卡|