原創|其它|編輯:郝浩|2009-09-25 13:48:57.000|閱讀 773 次
概述:Windows Mobile Sensors API庫的一個重要的功能是自動發現(detect)和判斷(determine)設備類型,調用相應設備(HTC或者Samsung)上的Sensor API,并返回統一的結果。因此該庫不能依賴于任何設備的上的Sensor庫。因此產生了動態加載各自設備上Sensor庫的需求。
# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
Windows Mobile Sensors API庫的一個重要的功能是自動發現(detect)和判斷(determine)設備類型,調用相應設備(HTC或者Samsung)上的Sensor API,并返回統一的結果。因此該庫不能依賴于任何設備的上的Sensor庫。因此產生了動態加載各自設備上Sensor庫的需求。關于Windows Mobile Sensors API庫的開發可以參考下面的文章:
本文以Windows Mobile Sensors API庫為例子講述在Windows Mobile下使用Native C++動態加載DLL的方法。
使用Native C++的開發,一般使用靜態加載的方法加載DLL,所謂靜態加載就是在程序編譯時(Compile Time)直接調用DLL的頭文件定義的函數,鏈接時(Link Time)鏈接*.lib文件指向DLL的接口,在程序開始運行時(Run Time Start up)加載DLL。
下面講述使用靜態加載DLL的方法,在程序中需要指定加載的*.lib文件,用于鏈接(Link)。
#pragma comment(lib, "SamsungMobileSDK_1.lib")
使用靜態加載的DLL可以直接調用頭文件定義的函數,例如:
SmiAccelerometerCapabilities cap;
if( SmiAccelerometerGetCapabilities(&cap) != SMI_SUCCESS)
{
throw;
}
SmiAccelerometerHandler h = &GetVectorHandler;
if(SmiAccelerometerRegisterHandler(1000, h) != SMI_SUCCESS)
{
throw;
}
SmiAccelerometerGetCapabilities()和SmiAccelerometerRegisterHandler()是定義在頭文件smiAccelerometer.h中的,可以直接調用,定義如下:
/**
* 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);
使用靜態加載的方法使用方面還是很方便的,可是在動態加載的時候就不能直接調用頭文件的函數了,增加了復雜度,下面會講到。
靜態加載DLL是比較簡單的開發方法,可是有個缺點是程序開始運行的時候就需要加載DLL,如果該DLL不存在,程序就不能啟動了。由于Windows Mobile Sensors API庫需要自適應具體的設備,也就是說Windows Mobile Sensors API庫不能依賴于具體設備的Sensor庫,所以不能使用靜態加載的方法來引用DLL。下面講述動態加載DLL的方法。
動態加載DLL,需要根據頭文件來定義指向函數的指針,如下:
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;
這些指向函數的指針可以對應下面的在smiAccelerometer.h頭文件的函數進行定義:
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();
定義是一一對應的。參數入口和返回值都必須完全一致。
初始化指向函數的指針的過程也就是動態加載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()函數動態加載DLL,GetProcAddress()根據函數的名字 加載函數的入口地址 到指向函數的指針。有點繞口,sorry。如果地址不為空,那么可以根據這個地址調用相應的函數。
調用函數的方法和靜態加載DLL的方法一樣,但是不是直接調用函數的名字,而是使用指向函數的指針來調用,下面的例子可以和靜態加載DLL函數調用的例子對比來看。
SmiAccelerometerCapabilities cap;
if( pfnSmiAccelerometerGetCapabilities(&cap) != SMI_SUCCESS)
{
throw;
}
SmiAccelerometerHandler h = &GetVectorHandler;
if(pfnSmiAccelerometerRegisterHandler(1000, h) != SMI_SUCCESS)
{
throw;
}
動態加載DLL的方法就完成了。
下面這段表述不對,請看下面的回復。.NET使用DllImport屬性進行P/Invoke不應該叫做動態加載,因為不能卸載,應該叫做按需加載,就是在call這個函數的時候才加載,而不是在程序啟動的時候加載。按需加載和靜態加載的區別是加載的時間不一樣。
{
在.NET里面P/Invoke一個DLL里面的函數全部都是動態加載(這是錯的,謝謝指出,這里應該叫做按需加載,動態加載的方法可以見到回復)的,使用DllImport屬性來定義。如果SmiAccelerometerUnregisterHandler()函數使用在.NET下會定義如下:
[DllImport("SamsungMobileSDK_1.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern uint SmiAccelerometerUnregisterHandler();
使用.NET比使用Native C++動態加載相對簡單。
}
這個項目還是在起步階段,當前實現了samsung的重力感應器,我把項目host到 了,我會持續改進,把各種sensors的實現到這個項目中。
源代碼:
環境:VS2008 + WM 6 professional SDK + Samsung Windows Mobile SDK
本站文章除注明轉載外,均為本站原創或翻譯。歡迎任何形式的轉載,但請務必注明出處、不得修改原文相關鏈接,如果存在內容上的異議請郵件反饋至chenjj@fc6vip.cn
文章轉載自:博客園