社区编辑申请
注册/登录
浅析C++动态加载DLL在Windows Mobile下实现
开发 后端 移动开发
这里我们将简单介绍Windows Mobile下Native C++动态加载DLL的实现,希望能对大家有所帮助。

我们将在这里为大家讲解Windows Mobile下Native C++动态加载DLL的实现,一般来说静态加载是很简单的事情,我们在本文中也将会提到。主要还是讲解C++动态加载DLL。

简介

本文以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可以直接调用头文件定义的函数,例如:

  1. SmiAccelerometerCapabilities cap;
  2. if( SmiAccelerometerGetCapabilities(&cap) != SMI_SUCCESS){    throw;}
  3. SmiAccelerometerHandler h = &GetVectorHandler;if(SmiAccelerometerRegisterHandler(1000, h) != SMI_SUCCESS)
  4. {    throw;} 

SmiAccelerometerGetCapabilities()和SmiAccelerometerRegisterHandler()是定义在头文件smiAccelerometer.h中的,可以直接调用,定义如下:

使用静态加载的方法使用方面还是很方便的,可是在动态加载的时候就不能直接调用头文件的函数了,增加了复杂度,下面会讲到。

  1. /**  
  2. *  Start receiving accelerometer data periodically.   
  3.  
  4. *  The period interval must be a multiple of the callbackPeriod specified   
  5. *  in SmiAccelerometerCapabilities. If it is less than the callbackPeriod, it will be   
  6. *  set to the callbackPeriod. If it is not a multiple of the callbackPeriod, it will be   
  7. *  truncated to fit the value. ( (period / callbackPeriod)   
  8. * callbackPeriod )   
  9. *     
  10. *  Only one handler per process is allowed. Successive calls per process will replace the previous handler   
  11. *  function and period.   
  12. *  
  13. *  @param    period    [in]    callback interval.      
  14. *  @param    handler   [in]    callback function for every period interval.     
  15.  
  16. *  @return                      
  17. *                              SMI_SUCCESS on success   
  18. *  \n                          SMI_ERROR_INVALID_PARAMETER if the handler input parameter is NULL   
  19. *  \n                          SMI_ERROR_DEVICE_NOT_FOUND if the device is not present or supported   
  20. *  \n                          SMI_ERROR_CANNOT_ACTIVATE_SERVER if the sensor server cannot be started   
  21. */ SMI_API SMI_RESULT SmiAccelerometerRegisterHandler(UINT period, SmiAccelerometerHandler handler); 

C++动态加载DLL的方法

静态加载DLL是比较简单的开发方法,可是有个缺点是程序开始运行的时候就需要加载DLL,如果该DLL不存在,程序就不能启动了。由于Windows Mobile Sensors API库需要自适应具体的设备,也就是说Windows Mobile Sensors API库不能依赖于具体设备的Sensor库,所以不能使用静态加载的方法来引用DLL。下面讲述动态加载DLL的方法。

定义指向函数的指针

动态加载DLL,需要根据头文件来定义指向函数的指针,如下:

  1. typedef UINT (WINAPI * PFN_SmiAccelerometerGetVector)(SmiAccelerometerVector*);  
  2. typedef UINT (WINAPI * PFN_SmiAccelerometerGetCapabilities)(SmiAccelerometerCapabilities*);  
  3. typedef UINT (WINAPI * PFN_SmiAccelerometerRegisterHandler)(UINT, SmiAccelerometerHandler);typedef UINT (WINAPI * PFN_SmiAccelerometerUnregisterHandler)();  
  4. PFN_SmiAccelerometerGetVector pfnSmiAccelerometerGetVector;PFN_SmiAccelerometerGetCapabilities   
  5. pfnSmiAccelerometerGetCapabilities;PFN_SmiAccelerometerRegisterHandler   
  6. pfnSmiAccelerometerRegisterHandler;PFN_SmiAccelerometerUnregisterHandler pfnSmiAccelerometerUnregisterHandler; 

这些指向函数的指针可以对应下面的在smiAccelerometer.h头文件的函数进行定义:

  1. SMI_API SMI_RESULT SmiAccelerometerGetVector(SmiAccelerometerVector *accel);  
  2. SMI_API SMI_RESULT SmiAccelerometerGetCapabilities(SmiAccelerometerCapabilities *capabilities);  
  3. SMI_API SMI_RESULT SmiAccelerometerRegisterHandler(UINT period, SmiAccelerometerHandler handler);  
  4. SMI_API SMI_RESULT SmiAccelerometerUnregisterHandler(); 

定义是一一对应的。参数入口和返回值都必须完全一致。

初始化指向函数的指针

初始化指向函数的指针的过程也就是动态加载DLL的过程,代码如下:

  1. #define SAMSUNG_SENSOR_DLL  
  2. L"SamsungMobilesdk_1.dll"HMODULE hSensorLib = LoadLibrary (SAMSUNG_SENSOR_DLL);if (NULL == hSensorLib){      
  3. printf("Unable to load Samsung Sensor DLL\n");      
  4. throw std::runtime_error("Unable to load Samsung Sensor DLL");}  
  5. pfnSmiAccelerometerGetVector = (PFN_SmiAccelerometerGetVector)      
  6. GetProcAddress(hSensorLib, L"SmiAccelerometerGetVector");pfnSmiAccelerometerGetCapabilities = (PFN_SmiAccelerometerGetCapabilities)      
  7. GetProcAddress(hSensorLib, L"SmiAccelerometerGetCapabilities");pfnSmiAccelerometerRegisterHandler = (PFN_SmiAccelerometerRegisterHandler)      
  8. GetProcAddress(hSensorLib, L"SmiAccelerometerRegisterHandler");pfnSmiAccelerometerUnregisterHandler = (PFN_SmiAccelerometerUnregisterHandler)     
  9. GetProcAddress(hSensorLib, L"SmiAccelerometerUnregisterHandler");if (NULL == pfnSmiAccelerometerGetVector){    printf("Unable to find entry point of SmiAccelerometerGetVector\n");      
  10. throw std::runtime_error("Unable to find entry point of SmiAccelerometerGetVector");}if (NULL == pfnSmiAccelerometerGetCapabilities){      
  11. printf("Unable to find entry point of SmiAccelerometerGetCapabilities\n");      
  12. throw std::runtime_error("Unable to find entry point of SmiAccelerometerGetCapabilities");}if (NULL == pfnSmiAccelerometerRegisterHandler){      
  13. printf("Unable to find entry point of SmiAccelerometerRegisterHandler\n");      
  14. throw std::runtime_error("Unable to find entry point of SmiAccelerometerRegisterHandler");}if (NULL == pfnSmiAccelerometerUnregisterHandler){      
  15. printf("Unable to find entry point of SmiAccelerometerUnregisterHandler\n");      
  16. throw std::runtime_error("Unable to find entry point of SmiAccelerometerUnregisterHandler");} 

LoadLibrary()函数动态加载DLL,GetProcAddress()根据函数的名字 加载函数的入口地址 到指向函数的指针。有点绕口,sorry。如果地址不为空,那么可以根据这个地址调用相应的函数。

调用函数

调用函数的方法和静态加载DLL的方法一样,但是不是直接调用函数的名字,而是使用指向函数的指针来调用,下面的例子可以和静态加载DLL函数调用的例子对比来看。

  1. SmiAccelerometerCapabilities cap;   
  2. if( pfnSmiAccelerometerGetCapabilities(&cap) != SMI_SUCCESS)  
  3.  {      
  4. throw;}SmiAccelerometerHandler h = &GetVectorHandler;  
  5. if(pfnSmiAccelerometerRegisterHandler(1000, h) != SMI_SUCCESS)  
  6. {    throw;} 

C++动态加载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

原文标题:Windows Mobile下Native C++动态加载DLL

链接:http://www.cnblogs.com/procoder/archive/2009/09/25/1573712.html

【编辑推荐】

  1. C++之运算符重载,输入输出流详细介绍
  2. C++、Java与C#的命名规范总结
  3. C++类成员函数的重载、覆盖与隐藏
  4. Eclipse下C/C++环境搭建
  5. Java与C++语言在作用域上的差异浅析
责任编辑:彭凡 来源: 博客园
相关推荐

2010-02-06 16:21:35

2010-01-08 16:00:46

C++编译器

2009-08-18 16:31:19

Visual C#编写

2011-06-24 09:01:20

Qt QLibrary dll

2009-08-05 16:29:18

C#调用C++动态链接

2011-04-08 09:52:44

2015-02-04 10:49:13

Visual C++C++Windows API

2009-08-28 16:14:26

C#实现加载动态库

2009-10-29 16:36:49

2015-05-13 09:57:14

同话题下的热门内容

八个流行的 Python 可视化工具包,你喜欢哪个?太赞了! 菜鸟利用Python实现网站自动签到Python办公自动化,五分钟掌握openpyxl操作!跟着 Guava 学 Java 之 不可变集合速度起飞!替代 pandas 的八个神库如何在 Windows 上写 Python 代码?优秀攻略来袭!浅谈Python+requests+pytest接口自动化测试框架的搭建C开发中段错误的三种调试方法

编辑推荐

使用Kotlin做开发一个月后的感想面试官问你什么是消息队列?把这篇甩给他!五大自动化测试的Python框架图文详解两种算法:深度优先遍历(DFS)和广度优先遍历(BFS)2018年最流行的十大编程语言,其中包括你用的语言吗?
我收藏的内容
点赞
收藏

AISummit人工智能大会