VC动态库可以嵌套调用

来源:互联网 发布:淘宝分享赚怎么赚钱? 编辑:程序博客网 时间:2024/05/03 12:02
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,它的工程设置中,依然可以追加依赖的静态库。

 

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