如何在Windows Mobile下使用Native C++動態載入DLL

來源:互聯網
上載者:User
背景

Windows Mobile Sensors API庫的一個重要的功能是自動探索(detect)和判斷(determine)裝置類型,調用相應裝置(HTC或者Samsung)上的Sensor API,並返回統一的結果。因此該庫不能依賴於任何裝置的上的Sensor庫。因此產生了動態載入各自裝置上Sensor庫的需求。關於Windows Mobile Sensors API庫的開發可以參考下面的文章:

Mobile Sensors API - Native unified APIs for Windows Mobile Sensors

Windows Mobile下的重力感應器(Gravitational Sensor)開發

Windows Mobile下使用CppUnitLite輸出測試結果

Windows Mobile Sensors API庫的設計

 

簡介

本文以Windows Mobile Sensors API庫為例子講述在Windows Mobile下使用Native C++動態載入DLL的方法。

 

靜態載入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,如果該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的世界

下面這段表述不對,請看下面的回複。.NET使用DllImport屬性進行P/Invoke不應該叫做動態載入,因為不能卸載,應該叫做按需載入,就是在call這個函數的時候才載入,而不是在程式啟動的時候載入。按需載入和靜態載入的區別是載入的時間不一樣。
{

在.NET裡面P/Invoke一個DLL裡面的函數全部都是動態載入(這是錯的,謝謝Wuya指出,這裡應該叫做按需載入,動態載入的方法可以見Wuya到回複)的,使用DllImport屬性來定義。如果SmiAccelerometerUnregisterHandler()函數使用在.NET下會定義如下:

[DllImport("SamsungMobileSDK_1.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern uint SmiAccelerometerUnregisterHandler();

使用.NET比使用Native C++動態載入相對簡單。

}

關於Mobile Sensors API項目

這個項目還是在起步階段,當前實現了samsung的重力感應器,我把項目host到 Mobile Sensors API - Native unified APIs for Windows Mobile Sensors 了,我會持續改進,把各種sensors的實現到這個項目中。

原始碼:http://mobilesensor.codeplex.com/SourceControl/ListDownloadableCommits.aspx

環境:VS2008 + WM 6 professional SDK + Samsung Windows Mobile SDK

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.