C++:关于库项目的生成和使用

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/dashumak/article/details/85617139

一、库项目的生成

  • 静态库:函数和数据被编译进一个二进制文件(.LIB文件)。在使用的静态库编译链接可执行文件时,链接器从库中复制这些函数并编译到exe文件当中。也就是说发布exe文件时,是不需要发布被使用的静态库的。
  • 静态库的项目配置:(1)项目-> 属性->常规->“MFC的使用”选择“在静态库中使用MFC”(2)进入项目-> 属性->C/C++->代码生成->*“运行库”选择“多线程调试MTd”*或者“多线程MT”,如果是Debug模式选择前者,Release模式选择后者。
  • 动态库:动态库项目生成两个文件引入库(.lib)和一个DLL(.dll)。注意这个lib文件时不同于上边的LIB文件的。引入库文件(.lib)包含改DLL导出的函数名和变量名,而.dll文件包含该库实际的函数和数据。当使用动态库编程生成exe文件时只需要lib文件即可,但是发布并运行exe文件时需要加载相应的dll文件。
  • 动态库的项目配置:(1)项目-> 属性->常规->“MFC的使用”选择“在共享DLL中使用MFC”(2)项目-> 属性->C/C++->代码生成->*“运行库”选择“多线程调试DLL(/MDd)”*或者“多线程DLL(/MD)”,如果是Debug模式选择前者,Release模式选择后者。
  • /MT 的意思就是使用微软的多线程静态链接库;/MD 的意思就是使用微软的多线程动态链接库。不要混合使用运行时库的静态版本和动态版本。在一个进程中使用同一个库的多个版本时会导致问题,经常提示已在.obj中定义,因为库副本中的静态数据不与其他库副本共享。链接器禁止在 .exe 文件内部既使用静态版本又使用动态版本链接。

二、库项目函数的导出和导入

如果我们的程序想要使用(导入/加载)某个DLL中的函数,那么该函数必须在DLL中是已经导出的。

1、从DLL中导出函数

  • def文件:只需要在EXPORT后边加上要导出的函数名就行(只需要函数名,不需要形参)。其实def文件的功能相当于extern “C” __declspec(dllexport)
  • 使用_declspec(dllexport)声明导出函数(既可以显示又可以隐时)
    dllexport是在这些类、函数以及数据的申明的时候使用。使用了(dllexport)关键字,相当于声明了紧接在(dllexport)关键字后面的相关内容是可以为其他程序使用的。
  • Dll文件中可以同时使用上述两种方法,但是网上大家都推荐使用第二种,好像第一种有的时候函数名会自己变。

2、隐式链接方式加载DLL

首先需要配置需要的lib文件,之后再采用extern或_declspec(dllimport)声明。配置lib文件有两种,一种是在项目属性中配置,另一种是在程序中加入下述代码(比如说使用的是A.lib文件),这两种方式效果是一样的。

#include "A.h"
#pragma comment(lib,"A.lib")
  • 可以使用extern声明库函数,即在使用之前,用extern声明一下dll导出的函数即可,如extern int add(int a,int b)。但是还是建议用下边这种方式:
  • 使用_declspec(dllimport)声明库函数。
    dllimport关键字是在外部程序需要使用DLL内相关内容时使用的关键字。当一个外部程序要使用DLL内部代码(类,函数,全局变量)时,只需要在 程序内部使用(dllimport)关键字声明需要使用的代码就可以了。
    _declspec(dllexport)_declspec(dllimport)是相互呼应,只有在DLL内部用dllexport作了声明,才能 在外部函数中用dllimport导入相关代码。实际上,在应用程序访问DLL时,实际上就是应用程序中的导入函数与DLL文件中的导出函数进行链接。

3、关于__declspec(dllexport)和__declspec(dllimport)的使用

经常是在.h文件中声明函数/类/数据的导出和导入,那么问题来了,库文件的.h文件既被库项目加载(这个时候应该是dllexport)又被将来使用库文件的项目加载(这个时候应该是dllimport),那么该怎么办呢,应当这么办:
在库项目的开头定义宏DLLProvider,然后在需要的.h文件中加入这样的代码,以后当使用dllexport或dllimport的时候,都使用DLL_EXPORT_IMPORT就行了。

 #ifdef DLLProvider
 #define DLL_EXPORT_IMPORT __declspec(dllexport) //在库项目中使用
 #else
 #define DLL_EXPORT_IMPORT __declspec(dllimport)//在使用dll的项目中使用
 #endif

三、其他关键的命令字

1、extern"C"

我们经常在程序(尤其是一些年代比较久,比如说早期的库文件里)里见到这样的代码

#ifdef __cplusplus 
extern "C" { 
#endif
...
#ifdef __cplusplus
  }
#endif

这个宏#ifdef __cplusplus意思是说,如果该文件是Cpp文件,extern "C" {}生效。当Cpp文件中出现这些代码,意味着花括号里边的代码是以C语言的编译规则生成汇编语言。
虽然C++是在C语言的基础上发展起来的,但是有些C代码和C++的编译规则存在一定差异。为了兼容这部分代码,C++创始人制定了上述的解决方法,在C++文件(也就是cpp文件)允许C语言代码直接存在,只需要在头上声明一下这部分代码需要按C语言的方法进行编译,也就是extern "C"的存在

猜你喜欢

转载自blog.csdn.net/dashumak/article/details/85617139
今日推荐