淺析C++動態(tài)加載DLL在Windows Mobile下實(shí)現(xiàn)
我們將在這里為大家講解Windows Mobile下Native C++動態(tài)加載DLL的實(shí)現(xiàn),一般來說靜態(tài)加載是很簡單的事情,我們在本文中也將會提到。主要還是講解C++動態(tài)加載DLL。
簡介
本文以Windows Mobile Sensors API庫為例子講述在Windows Mobile下使用Native C++動態(tài)加載DLL的方法。
靜態(tài)加載DLL的方法
使用Native C++的開發(fā),一般使用靜態(tài)加載的方法加載DLL,所謂靜態(tài)加載就是在程序編譯時(shí)(Compile Time)直接調(diào)用DLL的頭文件定義的函數(shù),鏈接時(shí)(Link Time)鏈接*.lib文件指向DLL的接口,在程序開始運(yùn)行時(shí)(Run Time Start up)加載DLL。
下面講述使用靜態(tài)加載DLL的方法,在程序中需要指定加載的*.lib文件,用于鏈接(Link)。
#pragma comment(lib, "SamsungMobileSDK_1.lib")
使用靜態(tài)加載的DLL可以直接調(diào)用頭文件定義的函數(shù),例如:
- SmiAccelerometerCapabilities cap;
 - if( SmiAccelerometerGetCapabilities(&cap) != SMI_SUCCESS){ throw;}
 - SmiAccelerometerHandler h = &GetVectorHandler;if(SmiAccelerometerRegisterHandler(1000, h) != SMI_SUCCESS)
 - { throw;}
 
SmiAccelerometerGetCapabilities()和SmiAccelerometerRegisterHandler()是定義在頭文件smiAccelerometer.h中的,可以直接調(diào)用,定義如下:
使用靜態(tài)加載的方法使用方面還是很方便的,可是在動態(tài)加載的時(shí)候就不能直接調(diào)用頭文件的函數(shù)了,增加了復(fù)雜度,下面會講到。
- /**
 - * Start receiving accelerometer data periodically.
 - *
 - * The period interval must be a multiple of the callbackPeriod specified
 - * in SmiAccelerometerCapabilities. If it is less than the callbackPeriod, it will be
 - * set to the callbackPeriod. If it is not a multiple of the callbackPeriod, it will be
 - * truncated to fit the value. ( (period / callbackPeriod)
 - * callbackPeriod )
 - *
 - * Only one handler per process is allowed. Successive calls per process will replace the previous handler
 - * function and period.
 - *
 - * @param period [in] callback interval.
 - * @param handler [in] callback function for every period interval.
 - *
 - * @return
 - * SMI_SUCCESS on success
 - * \n SMI_ERROR_INVALID_PARAMETER if the handler input parameter is NULL
 - * \n SMI_ERROR_DEVICE_NOT_FOUND if the device is not present or supported
 - * \n SMI_ERROR_CANNOT_ACTIVATE_SERVER if the sensor server cannot be started
 - */ SMI_API SMI_RESULT SmiAccelerometerRegisterHandler(UINT period, SmiAccelerometerHandler handler);
 
C++動態(tài)加載DLL的方法
靜態(tài)加載DLL是比較簡單的開發(fā)方法,可是有個(gè)缺點(diǎn)是程序開始運(yùn)行的時(shí)候就需要加載DLL,如果該DLL不存在,程序就不能啟動了。由于Windows Mobile Sensors API庫需要自適應(yīng)具體的設(shè)備,也就是說Windows Mobile Sensors API庫不能依賴于具體設(shè)備的Sensor庫,所以不能使用靜態(tài)加載的方法來引用DLL。下面講述動態(tài)加載DLL的方法。
定義指向函數(shù)的指針
動態(tài)加載DLL,需要根據(jù)頭文件來定義指向函數(shù)的指針,如下:
- typedef UINT (WINAPI * PFN_SmiAccelerometerGetVector)(SmiAccelerometerVector*);
 - typedef UINT (WINAPI * PFN_SmiAccelerometerGetCapabilities)(SmiAccelerometerCapabilities*);
 - typedef UINT (WINAPI * PFN_SmiAccelerometerRegisterHandler)(UINT, SmiAccelerometerHandler);typedef UINT (WINAPI * PFN_SmiAccelerometerUnregisterHandler)();
 - PFN_SmiAccelerometerGetVector pfnSmiAccelerometerGetVector;PFN_SmiAccelerometerGetCapabilities
 - pfnSmiAccelerometerGetCapabilities;PFN_SmiAccelerometerRegisterHandler
 - pfnSmiAccelerometerRegisterHandler;PFN_SmiAccelerometerUnregisterHandler pfnSmiAccelerometerUnregisterHandler;
 
這些指向函數(shù)的指針可以對應(yīng)下面的在smiAccelerometer.h頭文件的函數(shù)進(jìn)行定義:
- SMI_API SMI_RESULT SmiAccelerometerGetVector(SmiAccelerometerVector *accel);
 - SMI_API SMI_RESULT SmiAccelerometerGetCapabilities(SmiAccelerometerCapabilities *capabilities);
 - SMI_API SMI_RESULT SmiAccelerometerRegisterHandler(UINT period, SmiAccelerometerHandler handler);
 - SMI_API SMI_RESULT SmiAccelerometerUnregisterHandler();
 
定義是一一對應(yīng)的。參數(shù)入口和返回值都必須完全一致。
初始化指向函數(shù)的指針
初始化指向函數(shù)的指針的過程也就是動態(tài)加載DLL的過程,代碼如下:
- #define SAMSUNG_SENSOR_DLL
 - L"SamsungMobilesdk_1.dll"HMODULE hSensorLib = LoadLibrary (SAMSUNG_SENSOR_DLL);if (NULL == hSensorLib){
 - printf("Unable to load Samsung Sensor DLL\n");
 - throw std::runtime_error("Unable to load Samsung Sensor DLL");}
 - pfnSmiAccelerometerGetVector = (PFN_SmiAccelerometerGetVector)
 - GetProcAddress(hSensorLib, L"SmiAccelerometerGetVector");pfnSmiAccelerometerGetCapabilities = (PFN_SmiAccelerometerGetCapabilities)
 - GetProcAddress(hSensorLib, L"SmiAccelerometerGetCapabilities");pfnSmiAccelerometerRegisterHandler = (PFN_SmiAccelerometerRegisterHandler)
 - GetProcAddress(hSensorLib, L"SmiAccelerometerRegisterHandler");pfnSmiAccelerometerUnregisterHandler = (PFN_SmiAccelerometerUnregisterHandler)
 - GetProcAddress(hSensorLib, L"SmiAccelerometerUnregisterHandler");if (NULL == pfnSmiAccelerometerGetVector){ printf("Unable to find entry point of SmiAccelerometerGetVector\n");
 - throw std::runtime_error("Unable to find entry point of SmiAccelerometerGetVector");}if (NULL == pfnSmiAccelerometerGetCapabilities){
 - printf("Unable to find entry point of SmiAccelerometerGetCapabilities\n");
 - throw std::runtime_error("Unable to find entry point of SmiAccelerometerGetCapabilities");}if (NULL == pfnSmiAccelerometerRegisterHandler){
 - printf("Unable to find entry point of SmiAccelerometerRegisterHandler\n");
 - throw std::runtime_error("Unable to find entry point of SmiAccelerometerRegisterHandler");}if (NULL == pfnSmiAccelerometerUnregisterHandler){
 - printf("Unable to find entry point of SmiAccelerometerUnregisterHandler\n");
 - throw std::runtime_error("Unable to find entry point of SmiAccelerometerUnregisterHandler");}
 
LoadLibrary()函數(shù)動態(tài)加載DLL,GetProcAddress()根據(jù)函數(shù)的名字 加載函數(shù)的入口地址 到指向函數(shù)的指針。有點(diǎn)繞口,sorry。如果地址不為空,那么可以根據(jù)這個(gè)地址調(diào)用相應(yīng)的函數(shù)。
調(diào)用函數(shù)
調(diào)用函數(shù)的方法和靜態(tài)加載DLL的方法一樣,但是不是直接調(diào)用函數(shù)的名字,而是使用指向函數(shù)的指針來調(diào)用,下面的例子可以和靜態(tài)加載DLL函數(shù)調(diào)用的例子對比來看。
- SmiAccelerometerCapabilities cap;
 - if( pfnSmiAccelerometerGetCapabilities(&cap) != SMI_SUCCESS)
 - {
 - throw;}SmiAccelerometerHandler h = &GetVectorHandler;
 - if(pfnSmiAccelerometerRegisterHandler(1000, h) != SMI_SUCCESS)
 - { throw;}
 
C++動態(tài)加載DLL的方法就完成了。
.NET的世界
下面這段表述不對,請看下面的回復(fù)。.NET使用DllImport屬性進(jìn)行P/Invoke不應(yīng)該叫做動態(tài)加載,因?yàn)椴荒苄遁d,應(yīng)該叫做按需加載,就是在call這個(gè)函數(shù)的時(shí)候才加載,而不是在程序啟動的時(shí)候加載。按需加載和靜態(tài)加載的區(qū)別是加載的時(shí)間不一樣。
{
在.NET里面P/Invoke一個(gè)DLL里面的函數(shù)全部都是動態(tài)加載(這是錯(cuò)的,謝謝Wuya指出,這里應(yīng)該叫做按需加載,動態(tài)加載的方法可以見Wuya到回復(fù))的,使用DllImport屬性來定義。如果SmiAccelerometerUnregisterHandler()函數(shù)使用在.NET下會定義如下:
[DllImport("SamsungMobileSDK_1.dll", CharSet = CharSet.Auto, SetLastError = true)]private static extern uint SmiAccelerometerUnregisterHandler();使用.NET比使用Native C++動態(tài)加載相對簡單。
}
關(guān)于Mobile Sensors API項(xiàng)目
這個(gè)項(xiàng)目還是在起步階段,當(dāng)前實(shí)現(xiàn)了samsung的重力感應(yīng)器,我把項(xiàng)目host到 Mobile Sensors API - Native unified APIs for Windows Mobile Sensors 了,我會持續(xù)改進(jìn),把各種sensors的實(shí)現(xiàn)到這個(gè)項(xiàng)目中。
源代碼:http://mobilesensor.codeplex.com/SourceControl/ListDownloadableCommits.aspx
環(huán)境:VS2008 + WM 6 professional SDK + Samsung Windows Mobile SDK
原文標(biāo)題:Windows Mobile下Native C++動態(tài)加載DLL
鏈接:http://www.cnblogs.com/procoder/archive/2009/09/25/1573712.html
【編輯推薦】















 
 
 
 
 
 
 