VS2013生成自己的工程库

什么是程序库?

库是写好的现有的,成熟的,可以复用的代码。现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常。比如你经常使用的STL(Standard Template Library)也是库,有了STL你才能方便地使用std::string、std::cout这些类。

本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存,被别的程序调用执行。C++的库有两种:静态库和动态库。将一个程序编译成可执行文件一般经过 预编译–>编译–>链接 这几个过程,而静态库与动态库的区别主要体现在链接这个过程。

静态库:

在链接阶段,会将编译的目标文件.obj 与引用到的库.lib 一起链接打包到可执行文件exe(也称为目标代码)中,程序运行时将不再需要该静态库。

因此最终链接成的可执行文件(.exe)体积较大。在Windows中一般以.lib为后缀名,在Linux中一般以.a为后缀名。

动态库:

在链接阶段,动态库.dll并没有真正被连接到目标代码中,只是将这个动态库的声明链接到目标代码中(这样程序运行时才知道怎样使用这个动态库),动态库.dll依然是独立存在的,只有在程序运行是才会将.dll载入到内存中被程序调用。因此程序运行时必须要有这个动态库且放在正确的路径中。

因此最终链接成的可执行文件(.exe)体积较小。在Windows中一般以.dll为后缀名,在Linux中一般以.so为后缀名。

静态库与动态库的区别:

特点 静态库 动态库
对函数库的链接时机 在编译的链接阶段完成的 推迟到程序运行的时期
运行过程与库的关系 程序在运行时与静态库再无瓜葛 程序在运行时与动态库库需要一直存在且路径正确
是否链接到可执行文件 静态库被链接合成一个可执行文件 动态库不会被链接到可执行文件中
目标文件大小 体积较大 体积较小
内存占用度 占用内存。如果多个程序使用了同一个静态库,每一个程序者会包含这个静态库 节约内存。如果多个程序使用了同一个动态库,可以实现进程之间的资源共享(因此动态库也称为共享库)
程序移植 移植方便 移植不太方便,需要所有动态库的头文件
程序升级 程序升级麻烦,需要下载整个程序进行升级 程序升级更简单,只需要升级某个DLL或某个程序,下载一个升级包即可
编译出的结果文件 ProjectName.lib ProjectName.lib+ProjectName.dll, 这里的ProjectName.lib与静态库的.lib文件不同,这只是一个导入库,只包含了地址符号表等,以便调用方的程序能找到对应的函数,真正的库文件是ProjectName.dll

编译自己的工程库

假设我们有这样一个工程,这个工程的作用就是提供一些常用的工具类和方法,然后我们要将这个工程编译成库提供给别人使用。

编译静态库

假设我们已经建好工程并写好了相应的代码: 
工程目录 
工程目录

Utils.h:

[plain] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. //===============================================================  
  2. //Summary:  
  3. //          Utils 类, 工具类  
  4. //FileName:  
  5. //          Utils.h  
  6. //Remarks:  
  7. //          ...  
  8. //Date:  
  9. //          2015/10/4  
  10. //Author:  
  11. //          Administrator(luoweifu@126.com)  
  12. //===============================================================  
  13.   
  14. #ifndef __UTILS_H__  
  15. #define __UTILS_H__  
  16.   
  17. #include <string>  
  18. #include <strstream>  
  19. //#include <cstdlib>  
  20.   
  21. class Utils  
  22. {  
  23. public:  
  24.     Utils(void);  
  25.     ~Utils(void);  
  26.   
  27. public:  
  28.     //---------------------------------------------------------------  
  29.     //function:   
  30.     //          WString2String wstring 到 string 的转换  
  31.     //Access:  
  32.     //           public    
  33.     //Parameter:  
  34.     //          [in] const std::wstring & ws - wstring字符串  
  35.     //Returns:  
  36.     //          std::string - string字符串  
  37.     //Remarks:  
  38.     //          些方法跨平台,可移植版本  
  39.     //author:   luoweifu  
  40.     //---------------------------------------------------------------  
  41.     static std::string WString2String(const std::wstring& ws);  
  42.   
  43.     //---------------------------------------------------------------  
  44.     //function:   
  45.     //          String2WString string 到 wstring 的转换  
  46.     //Access:  
  47.     //           public    
  48.     //Parameter:  
  49.     //          [in] const std::string & s - string 字符串  
  50.     //Returns:  
  51.     //          std::wstring - wstring字符串  
  52.     //Remarks:  
  53.     //          些方法跨平台,可移植版本  
  54.     //author:    luoweifu  
  55.     //---------------------------------------------------------------  
  56.     static std::wstring String2WString(const std::string& s);  
  57.   
  58. };  
  59.   
  60. //---------------------------------------------------------------  
  61. //function:   
  62. //          ConvertToString 将int转换成string  
  63. //Parameter:  
  64. //          [in] int val - 要转换的变量  
  65. //Returns:  
  66. //          std::string - 转换后的字符串  
  67. //Remarks:  
  68. //          ...  
  69. //author:   luoweifu  
  70. //---------------------------------------------------------------  
  71. std::string ConvertToString(int val);  
  72.   
  73. #endif  //__UTILS_H__  

上述声明的实现参考后面的附录Utils.cpp

要编译成静态库,我们可以这样设置我们的工程: 

右键工程->Properties 

编译成静态库 
编译成静态库

然后右键Build就可以了,你可以在解决方案下的Debug(实际的情况中一般要编译成Release版本,设置的方法一样,这里的内容后一章中再讲)目录下就能看到Utils.lib,这就是编译出的库。要将这个库给别人使用,只要提供这个Utils.lib和这个工程的头文件就可以。将Utils.h拷贝到D:\ReleaseLibs\StaticLib\Includes,将Utils.lib拷贝到D:\ReleaseLibs\StaticLib\Libs,把D:\ReleaseLibs\StaticLib这个文件提供出去就可以了。静态库的使用请看后一小节使用静态库

编译动态库

与静态库相比,编译动态库要麻烦一些,一般要在导出函数的声明处加上_declspec(dllexport)关键字前缀。 

1. *Utils.h的声明如下

[plain] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. //===============================================================  
  2. //Summary:  
  3. //          Utils 类, 工具类  
  4. //FileName:  
  5. //          Utils.h  
  6. //Remarks:  
  7. //          ...  
  8. //Date:  
  9. //          2015/10/4  
  10. //Author:  
  11. //          Administrator(luoweifu@126.com)  
  12. //===============================================================  
  13.   
  14. #ifndef __UTILS_H__  
  15. #define __UTILS_H__  
  16.   
  17. #include <string>  
  18. #include <strstream>  
  19. //#include <cstdlib>  
  20.   
  21. //===============================================================  
  22.   
  23. //===============================================================  
  24.   
  25. class Utils  
  26. {  
  27. public:  
  28.     Utils(void);  
  29.     ~Utils(void);  
  30.   
  31. public:  
  32.     //---------------------------------------------------------------  
  33.     //function:   
  34.     //          Max 获得两个数中的最大值  
  35.     //Access:  
  36.     //           public    
  37.     //Parameter:  
  38.     //          [in] int nValue1 - 第一个数  
  39.     //          [in] int nValue2 - 每二个数  
  40.     //Returns:  
  41.     //          int - 最大值  
  42.     //Remarks:  
  43.     //          ...  
  44.     //author:   luoweifu  
  45.     //---------------------------------------------------------------  
  46.     static int Max(int nValue1, int nValue2);  
  47.   
  48.     //---------------------------------------------------------------  
  49.     //function:   
  50.     //          Min 获得两个数中的最小值  
  51.     //Access:  
  52.     //           public    
  53.     //Parameter:  
  54.     //          [in] int nValue1 - 第一个值  
  55.     //          [in] int nValue2 - 第二个值  
  56.     //Returns:  
  57.     //          int - 最小值  
  58.     //Remarks:  
  59.     //          ...  
  60.     //author:   luoweifu  
  61.     //---------------------------------------------------------------  
  62.     static int Min(int nValue1, int nValue2);  
  63.   
  64.     //---------------------------------------------------------------  
  65.     //function:   
  66.     //          Range 将一值限定在一个范围内  
  67.     //Access:  
  68.     //           public    
  69.     //Parameter:  
  70.     //          [in] int nMin - 最小值  
  71.     //          [in] int nMax - 最大值  
  72.     //Returns:  
  73.     //          int - 返回在限制在该范围内的一个值  
  74.     //Remarks:  
  75.     //          ...  
  76.     //author:   luoweifu  
  77.     //---------------------------------------------------------------  
  78.     static int Range(int nMin, int nMax, int nValue);  
  79. };  
  80.   
  81.   
  82. //---------------------------------------------------------------  
  83. //function:   
  84. //          ConvertToInt 将一个常量字符串转换成int类型数据  
  85. //Access:  
  86. //           public    
  87. //Parameter:  
  88. //          [in] const char * pStr - 常量字符串  
  89. //Returns:  
  90. //          int - 转换成的int值  
  91. //Remarks:  
  92. //          ...  
  93. //author:   luoweifu  
  94. //---------------------------------------------------------------  
  95. int ConvertToInt(const char* pStr);  
  96.   
  97. #endif  //__UTILS_H__  

  1. 要编译成动态库,我们可以这样设置我们的工程: 
    右键工程->Properties 
    设置编译的目标类型
    设置编译的目标类型

    设置预编译宏
    设置预编译宏

然后右键Build就可以了,你可以在解决方案下的Debug(实际的情况中一般要编译成Release版本,设置的方法一样,这里的内容后一章中再讲)目录下就能看到Utils.dll和Utils.lib,这就是编译出的库。要将这个库给别人使用,只要提供这个Utils.dll、Utils.lib和这个工程的头文件就可以。将Utils.h拷贝到D:\ReleaseLibs\DynamicLib\Includes,将Utils.dll和Utils.lib拷贝到D:\ReleaseLibs\DynamicLib\Libs,把D:\ReleaseLibs\DynamicLib这个文件提供出去就可以了。动态库的使用请看后一小节使用动态库

也许你要问为什么编译出的静态库是Utils.lib,编译出的动态库也有Utils.lib,这两个.lib文件是一样的吗? 
你比较一下两个.lib文件的大小就会发现相差很大(静态库的lib有235KB,动态库的lib只有2.7KB),所以肯定不是一样的啦!动态库对应的lib文件叫“导入库”,导入库只包含了地址符号表等,确保调用方的程序能找到对应函数的一些基本地址信息,而实际的执行代码位于DLL文件中。静态库的lib文件本身就包含了实际执行代码、符号表等。

使用导入(第三方)库

在实际的开发中经常要用第三方提供的库,如开源库,或大型系统中合作方提供的组件。如果使用呢?我们就以上面自己制作的库为例进行讲解。假设我们有一个工程TestProject要使用上面自己制作的Utils库。

使用静态库

  1. 右键工程->Properties,进行如下的设置。 

    设置头文件所在的路径
    设置头文件所在的路径

    设置lib库所在的路径
    设置lib库所在的路径

    设置要导入哪个lib库
    设置要导入哪个lib库

  2. 测试代码如下:

[plain] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. #include <iostream>  
  2. #include <tchar.h>  
  3. #include "Utils.h"  
  4.   
  5. int _tmain(int argc, _TCHAR* argv[])  
  6. {  
  7.     int nMax = Utils::Max(25, 37);  
  8.     std::cout << nMax << std::endl;  
  9.     int nMin = Utils::Min(10, 44);  
  10.     std::cout << nMin << std::endl;  
  11.     int nValue = Utils::Range(0, 100, 115);  
  12.     std::cout << nValue << std::endl;  
  13.     char* pStr = "1234";  
  14.     int nValue2 = ConvertToInt(pStr);  
  15.     std::cout << nValue2 << std::endl;  
  16.     return 0;  
  17. }  

使用动态库

  1. 右键TestProject工程->Properties,进行如下的设置。 

    设置头文件所在的路径
    设置头文件所在的路径 
    设置lib库所在的路径
    设置lib库所在的路径 
    设置要导入哪个导入库
    设置要导入哪个导入库

  2. 将Utils.dll放入与TestProject的输出文件TestProject.exe相同的路径下。这个很最重,不然会编译成功会是执行失败,因为找不到对应的.dll文件。

  3. 测试代码与静态库的一样。

附录

Utils.cpp

[plain] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. #include "Utils.h"  
  2.   
  3. Utils::Utils(void)  
  4. {  
  5. }  
  6.   
  7. Utils::~Utils(void)  
  8. {  
  9. }  
  10.   
  11.   
  12. int Utils::Max( int nValue1, int nValue2 )  
  13. {  
  14.     return nValue1 > nValue2 ? nValue1 : nValue2;  
  15. }  
  16.   
  17. int Utils::Min( int nValue1, int nValue2 )  
  18. {  
  19.     return nValue1 < nValue2 ? nValue1 : nValue2;  
  20. }  
  21.   
  22. int Utils::Range( int nMin, int nMax, int nValue )  
  23. {  
  24.     if (nMax < nMin)  
  25.     {  
  26.         int temp = nMin;  
  27.         nMin = nMax;  
  28.         nMax = temp;  
  29.     }  
  30.   
  31.     if (nValue < nMin)  
  32.     {  
  33.         return nMin;  
  34.     } else if (nValue > nMax)  
  35.     {  
  36.         return nMax;  
  37.     } else  
  38.     {  
  39.         return nValue;  
  40.     }  
  41. }  
  42.   
  43. int ConvertToInt( const char* pStr )  
  44. {  
  45.     int val;    
  46.     std::strstream ss;    
  47.     ss << pStr;    
  48.     ss >> val;    
  49.     return val;    
  50. }

测试结果:


下面是一个非常赞的链接
推荐链接:
http://blog.csdn.net/luoweifu/article/category/5837703
发布了347 篇原创文章 · 获赞 607 · 访问量 261万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 技术黑板 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览