天天看点

VC动态库可以嵌套调用

VC库编译的相关知识

一、动态库的调用方式

      在VC中,依赖库分为静态库(.lib)和动态库(.dll)两种。如果使用的是静态库,会把依赖的静态库中的内容编译到目标文件中。如果是使用的是动态库,则根据引用方式进行编译。

       动态库分为两部分:动态库静态链接(A.lib) 动态库(A.dll)。

动态库编译只需要在代码中包含动态库的头文件即可。

①动态库静态调用----隐式链接。 

有两种方式 引用。

方式一:在工程属性中配置。

项目->属性->链接 设置附加库目录和“输入”选项中设置静态库链接(A.lib) 

方式二:在代码中直接声明使用动态库链接。

项目->属性->链接 设置附加库目录

代码中添加

#pragma comment(lib, "A.lib")

链接器可以根据A.lib找到A.dll中相应的实现。

②动态库动态调用----显式链接。

通过Windows API LoadLiberary,通过GetProcAddress获取函数地址,然后调用。

这种方式不需要使用静态库链接(A.lib)

 运行时需要将DLL和可执行文件放在同一目录。

二、VC动态库嵌套调用

        VC动态库可以嵌套调用,当然最好是不进行嵌套调用。为了防止头文件嵌套包含,应该定义 #pragma once

例如:

动态库A的头文件 libA.h 定义:

#pragma once

 #ifdef LIBA_EXPORTS
 #define LIBA_API __declspec(dllexport)
 #else
 #define LIBA_API __declspec(dllimport)
 #endif

 #define PI_VALUE 3.1415926f

 // 此类是从 libA.dll 导出的
 class LIBA_API ClibA {
 public:
     ClibA(void);
     // 计算圆锥体体积。
     float TaperV(int r, int h);
     //圆面积
     float AreaCircle(int r);
 };

 extern LIBA_API int nlibA;

 LIBA_API int fnlibA(void);

 #ifndef LIBA_EXPORTS
 #    pragma comment(lib, "libA.lib")
 #endif

 //===========================
 动态库libB 的头文件 libB.h的定义如下:
 #pragma once

 #ifdef LIBB_EXPORTS
 #define LIBB_API __declspec(dllexport)
 #else
 #define LIBB_API __declspec(dllimport)
 #endif

 // 此类是从 libB.dll 导出的
 class LIBB_API ClibB {
 public:
     ClibB(void);
     // 圆柱体体积。
     int ClinderV(int r, int h);
 };

 extern LIBB_API int nlibB;

 LIBB_API int fnlibB(void);

 #ifndef LIBB_EXPORTS
 #       pragma comment(lib, "libB.lib")
 #endif

 //==========================
 libA.cpp

   
 #include "stdafx.h"
 #include "libA.h"
#include "libB.h"

 // 这是导出变量的一个示例
 LIBA_API int nlibA=0;

 // 这是导出函数的一个示例。
 LIBA_API int fnlibA(void)
 {
     return 42;
 }

 // 这是已导出类的构造函数。
 // 有关类定义的信息,请参阅 libA.h
 ClibA::ClibA()
 {
     return;
 }

float ClibA::TaperV( int r, int h )
 {
     ClibB clibb;
     return (float)clibb.ClinderV(r, h) / 3;
 }

 float ClibA::AreaCircle( int r )
 {
     return PI_VALUE * r * r;
 } 


 成员函数
   TaperV需要调用libB的成员函数。
 //==============================

 libB.cpp

 #include "stdafx.h"
 #include "libB.h"
 #include "libA.h"

 // 这是导出变量的一个示例
 LIBB_API int nlibB=0;

 // 这是导出函数的一个示例。
 LIBB_API int fnlibB(void)
 {
     return 42;
 }

 // 这是已导出类的构造函数。
 // 有关类定义的信息,请参阅 libB.h
 ClibB::ClibB()
 {
     return;
 }

int ClibB::ClinderV( int r, int h )
 {
     ClibA cliba;
     return cliba.AreaCircle(r) * h;
 }      

成员函数

ClinderV需要调用libA的成员函数。

      VC动态库相互嵌套并不会引起问题,但是最好不适用嵌套调用的方式。

首先理解了三个概念:

1.      静态链接库

这是一个名词,是.lib库。

2.      静态链接

在工程设置的Link项中,添加所要链接的.lib库,程序中包含其导出函数对应的头文件。再编译时,就会将使用到的静态库中的函数一同编译到目标文件中,目标文件可以是lib库,dll,exe,ocx等。

3.      动态链接

程序再运行时才装载要使用的函数。动态链接一般都是使用Dll——动态链接库。

一直都是使用动态库,经常是动态库链接一个静态库。最近想使用静态库链接一个静态库,可能要好几层,同事们都说不可以,可我觉得理论上没有问题,于是就试验了一下,事实证明是完全可以的。

1. 在VC6.0上,lib库的工程设置中,是没有追加静态库的地方的,只能再程序中使用语句#pragma   comment(lib,   "***.lib")来追加。

2. 在VS2005上,我使用的是VS2005,它的工程设置中,依然可以追加依赖的静态库。

在使用方式上没有什么特殊之处。