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

            VC++動態鏈接庫編程之DLL典型實例

            動態鏈接庫DLL實現了庫的共享,體現了代碼重用的思想。我們可以把廣泛的、具有共性的、能夠多次被利用的函數和類定義在庫中。這樣,在再次使用這些函數和類的時候,就不再需要重新添加與這些函數和類相關的代碼。具有共性的問題大致有哪些呢?筆者歸納如下:

              (1)通用的算法

              圖像處理、視頻音頻解碼、壓縮與解壓縮、加密與解密通常采用某些特定的算法,這些算法較固定且在這類程序中往往經常被使用。

              (2)純資源DLL

              我們可以從DLL中獲取資源,對于一個支持多種語言的應用程序而言,我們可以判斷操作系統的語言,并自動為應用程序加載與OS對應的語言。這是多語言支持應用程序的一般做法。

              (3)通信控制DLL

              串口、網口的通信控制函數如果由DLL提供則可以使應用程序輕松不少。在工業控制、modem程序甚至socket通信中,經常使用通信控制DLL。

              本節將給出DLL的三個典型應用實例。

              7.1 算法DLL

              我們直接用讀者的一個提問作為例子。

              宋寶華先生,您好!

              我在dev.yesky.com上看到你連載的《VC++動態鏈接庫編程》,覺得非常好。我以前主要是用Delphi的,C/C++學過,對Win32和VCL比較熟悉,但是沒有接觸過VC++,對MFC很陌生。這段時間和一個同學合作做光學成像的計算機模擬,用到傅立葉變換,手里面有例程是VC++寫的。我們的界面是用Delphi開發,需要將其傅立葉變換功能提出做一個DLL供Delphi調用。苦于不懂MFC,試了很多方法,都不成功,最后只得采用折衷方案,簡單修改一下程序,傳一個參數進去,當作exe來調用,才沒有耽擱后續進程。

              ……

              謝謝!

                    致

              禮!

                     某某

              學習過較高級別數學(概率統計與隨機過程)、信號與線性系統及數字信號處理的讀者應該知道,傅立葉變換是一種在信號分析中常用的算法,用于時域和頻域的相互轉換。FFT變換算法通用而有共性,我們適宜把它集成在一個DLL中。

              隨后,這位讀者提供了這樣的一個函數:

            /* 函數名稱:FFT()
            * 參數:
            * complex<double> * TD - 指向時域數組的指針
            * complex<double> * FD - 指向頻域數組的指針
            * r -2的冪數,即迭代次數
            * 返回值: 無。
            * 說明:該函數用來實現快速傅立葉變換
            */

            void FFT(complex<double> * TD, complex<double> * FD, int r)
            {
             LONG count; // 傅立葉變換點數
             int i,j,k; // 循環變量
             int bfsize,p; // 中間變量
             double angle; // 角度
             complex<double> *W,*X1,*X2,*X;
             count = 1 << r; //傅立葉變換點數

             // 分配運算所需存儲器

             W = new complex<double>[count / 2];
             X1 = new complex<double>[count];
             X2 = new complex<double>[count];

             // 計算加權系數

             for(i = 0; i < count / 2; i++)
             {
              angle = -i * PI * 2 / count;
              W[i] = complex<double> (cos(angle), sin(angle));
             }

             // 將時域點寫入X1

             memcpy(X1, TD, sizeof(complex<double>) * count);

             // 采用蝶形算法進行快速傅立葉變換

             for(k = 0; k < r; k++)
             {
              for(j = 0; j < 1 << k; j++)
              {
               bfsize = 1 << (r-k);
               for(i = 0; i < bfsize / 2; i++)
               {
                p = j * bfsize;
                X2[i + p] = X1[i + p] + X1[i + p + bfsize / 2];
                X2[i + p + bfsize / 2] = (X1[i + p] - X1[i + p + bfsize / 2]) * W[i * (1<<k)];
               }
              }
              X = X1;
              X1 = X2;
              X2 = X;
             }

             // 重新排序

             for(j = 0; j < count; j++)
             {
              p = 0;
              for(i = 0; i < r; i++)
              {
               if (j&(1<<i))
               {
                p+=1<<(r-i-1);
               }
              }
              FD[j]=X1[p];
             }

             // 釋放內存

             delete W;
             delete X1;
             delete X2;
            }

              既然有了FFT這個函數,我們要把它做在DLL中,作為DLL的一個接口將是十分簡單的,其步驟如下:

              (1)利用MFC向導建立一個非MFC DLL;

              (2)在工程中添加fft.h和fft.cpp兩個文件;

              fft.h的源代碼為:

            #ifndef FFT_H
            #define FFT_H

            #include <complex>

            using namespace std;
            extern "C" void __declspec(dllexport) __stdcall FFT(complex<double> * TD, complex<double> * FD, int r);

            #define PI 3.1415926
            #endif

            fft.cpp的源代碼為:

            /* 文件名:fft.cpp */

            #include "fft.h"
            void __stdcall FFT(complex<double> * TD, complex<double> * FD, int r)
            {
             …//讀者提供的函數代碼
            }

              在任何編程語言中使用Win32 API LoadLibrary都可以加載這個DLL,而使用GetProcAddress(hDll, "FFT")則可以獲得函數FFT的地址,讀者所提到的Delphi當然也不例外。

              這個DLL中有兩點需要注意:

              (1)使用extern "C"修飾函數聲明,否則,生成的DLL只能供C++調用;

              (2)使用__stdcall修飾函數聲明及定義,__stdcall是Windows API的函數調用方式。
            7.2純資源DLL

              我們在應用程序中產生如圖18所示的資源(對話框),單擊此處下載本工程


            圖18 中文對話框

              在與這個應用程序相同的工作區里利用MFC向導建立兩個簡單的DLL,把應用工程中的資源全選后分別拷貝到ChineseDll和EngLishDll,在EnglishDll工程的資源文件中搜索下面的語句:

            /////////////////////////////////////////////////////////////////////////////

            // Chinese (P.R.C.) resources

            #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
            #ifdef _WIN32
            LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
            #pragma code_page(936)
            #endif //_WIN32

              將其改為:

            /////////////////////////////////////////////////////////////////////////////
            // English (U.S.) resources

            #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
            #ifdef _WIN32

            LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US

            #pragma code_page(1252)
            #endif //_WIN32

              并將其中所有的中文翻譯為英文。這個DLL為我們提供了如圖19所示的對話框資源。


            圖19英文對話框

              修改應用工程的InitInstance()函數,在

            CResourceDllCallDlg dlg;
            m_pMainWnd = &dlg;
            int nResponse = dlg.DoModal();

              之前(即對話框顯示之前)添加如下代碼:

            //獲取操作系統的語言

            WORD wLangPID = PRIMARYLANGID( GetSystemDefaultLangID() );
            if( LANG_CHINESE == wLangPID )
            {
             hLanguageDll = LoadLibrary( "ChineseDll.dll" ); //加載中文資源
            }
            else
            {
             hLanguageDll = LoadLibrary( "EnglishDll.dll" ); //加載英文資源
            }

            if( NULL == hLanguageDll )
            {
             AfxMessageBox( "Load DLL failure" );
             return FALSE;
            }
            AfxSetResourceHandle( hLanguageDll ); //設置當前的資源句柄

              這樣的應用程序將具有自適應性質,在中文OS中顯示中文資源,在英文OS中則顯示英文資源。
            7.3通信控制DLL

              我們在這里舉一個串口通信類的例子。

              也許您需要了解一點串口通信的背景知識,其實串口到處都看得到,譬如PC機的COM口即為串行通訊口(簡稱串口)。如圖20,打開Windows的設備管理器,我們看到了COM口。

              在Windows系統,需通過DCB(Device Control Block)對串口進行配置。利用Windows API GetCommState函數可以獲取串口當前配置;利用SetCommState函數則可以設置串口通訊的參數。

              串行通信通常按以下四步進行:

              (1)打開串口;

              (2)配置串口;

              (3)數據傳送;

              (4)關閉串口。


            圖20 PC的串口

              由此可見,我們需要給串口控制DLL提供如下四個接口函數:

            //打開指定的串口,其參數port為端口號

            BOOL ComOpen(int port); //在這個函數里使用默認的參數設置串口

            //將打開的串口關閉

            void ComClose(int port);

            //將串口接收緩沖區中的數據放到buffer中

            int GetComData(char *buf, int buf_len);

            //將指定長度的數據發送到串口

            int SendDataToCom(LPBYTE buf,int buf_Len);

              下面給出了DLL接口的主要源代碼框架:

            //com.h:com類通信接口

            class AFX_EXT_CLASS com
            {
             public:
              ComOpen(int port)
              {
               …
              }
              int SendDataToCom(LPBYTE buf,int buf_Len)
              {
               …
              }
              int GetComData(char *buf, int buf_len)
              {
               …
              }
              void ComClose()
              {
               …
              }
             }

              我們編寫一控制臺程序來演示DLL的調用:

            #include <iostream>
            #include <exception>

            using namespace std;

            #include <windows.h>
            #include "com.h" //包含DLL中導出類的頭文件 int main(int argc, char *argv[])
            {
             try
             {
              char str[] = "com_class test";
              com com1;
              com1.ComOpen (1);
              for(int i=0; i<100; i++) //以同步方式寫com的buffer
              {
               Sleep(500);
               com1.SendDataToCom (str,strlen(str));
              }
              com1.ComClose ();
             }
             catch(exception &e)
             {
              cout << e.what() << endl;
             }
             return 0;
            }

              DLL的編寫與調用方法及主要應用皆已講完,在下一節里,我們將看到比較“高深”的主題――DLL木馬。曾幾何時,DLL木馬成為了病毒的一種十分重要的形式,是DLL的什么特性使得它能夠成為一種病毒?下一節我們將揭曉謎底。

            posted on 2009-06-09 21:20 wrh 閱讀(303) 評論(0)  編輯 收藏 引用

            導航

            <2010年7月>
            27282930123
            45678910
            11121314151617
            18192021222324
            25262728293031
            1234567

            統計

            常用鏈接

            留言簿(19)

            隨筆檔案

            文章檔案

            收藏夾

            搜索

            最新評論

            閱讀排行榜

            評論排行榜

            亚洲精品乱码久久久久久蜜桃不卡| 91麻豆精品国产91久久久久久| 亚洲精品成人网久久久久久| 亚洲午夜福利精品久久| 性欧美大战久久久久久久| 久久无码中文字幕东京热| 色婷婷综合久久久中文字幕 | 久久精品国产国产精品四凭| 欧美日韩成人精品久久久免费看| 精品久久亚洲中文无码| 亚洲乱亚洲乱淫久久| 久久午夜夜伦鲁鲁片免费无码影视| www.久久热.com| 久久久久久免费视频| 精品国产青草久久久久福利| 亚洲精品国产字幕久久不卡| 久久综合色区| 精品无码久久久久久久久久| 久久精品国产清高在天天线| 午夜精品久久久久| 国产精品伊人久久伊人电影| 久久这里只有精品首页| 久久久久亚洲av无码专区导航| 香蕉久久久久久狠狠色| 四虎久久影院| 久久久WWW成人免费精品| 国内精品久久人妻互换| 色偷偷偷久久伊人大杳蕉| 欧美精品福利视频一区二区三区久久久精品| 精品久久久久久成人AV| 久久婷婷人人澡人人爽人人爱| 色婷婷综合久久久久中文字幕| 国产精品VIDEOSSEX久久发布| 久久综合狠狠色综合伊人| 久久精品国产99久久无毒不卡| 婷婷久久香蕉五月综合加勒比| 人妻无码αv中文字幕久久琪琪布| 久久中文字幕视频、最近更新| 日韩久久无码免费毛片软件| 久久高清一级毛片| 中文字幕精品久久|