windows生成库文件

库文件的生成,包括静态库lib与动态库dll,需要改变编译输出的生成命令,可以一开始生成对应的库工程(或者在工程属性->常规->配置类型更改)。

附基本对应命令:

gcc –c -L

.o

Cl /c /link

.obj

ar

.a

lib

.lib

ld

.o

link

.dll

其中,动态库dll需要在所输出的“对象”前添加_declspec(dllexport)声明。

对于库的使用
,除了需要包含对应的头文件,静态库需要在文件中添加#prama comment(lib,"cof.lib")
或者在有以下几种情况:
1) 相同解决方案下,可在属性面板“框架与引用”添加静态库工程,并”c++”中添加include file即可
2) 在“link”的附加依赖项添加库的目录,在“输入”中使用添加cof.lib(与pragma同)

 

windows动态库有两种使用方式,使用lib导入库,二是使用window api

1)  lib导入库的使用方式与静态库同,但是头文件中的“对象”最好有_declspec(dllimport)声明

2)  window api不需要头文件

 

导出类:

1 简单例子

dllExample.h:

#pragma once

#ifdef DLL_EXPORTS

#define DLL_API __declspec(dllexport)

#else                                       

#define DLL_API __declspec(dllimport)

#endif

 

extern DLL_API int a;

class DLL_API ExportClass

{

pirvate:

    int x;

public:

    void foo();

};

dllExample.cpp:

#define DLL_EXPORTS

#include "dllExample.h"

int a = 4;

void ExportClass::foo()

{

    //do something...

    return;

}

 

不过这种简单的DLL导出存在一个限制,如果我们导出的类中含有非C++基础类型:

dllExample.h:

#pragma once

 

#ifdef DLL_EXPORTS

#define DLL_API __declspec(dllexport)

#else

#define DLL_API __declspec(dllimport)

#endif

 

class DLL_API ExportClass

{

pirvate:

    std::string x; //此处的string类型导出是不安全的

public:

    void foo();

};

我们知道, 对于STL,微软为每个版本的VS都有不同的实现,VS2008(VC90),VS2010(VC100),VS2013(VC120)。
由于不同的STL的实现,我们不能在不同的版本见直接传递std::string, 否则运行期可能出现不可预知的错误。
而事实上我们在ExportClass中的std::string x变量是不希望被外部直接使用的,也就是并没有export的必要,事实上,不建议让dll向外导出任何关于非C++基础类型的定义。
但是由于ExportClass需要向外导出(因为需要使用foo()函数),应该如何处理这样的矛盾呢?

对于这样的问题,我们需要使用C++的抽象类(其实就是java中的interface概念)来解决:
我们需要:
1. 申明一个只有纯虚函数和C++基础类型的基类,所有需要向外部导出的定义都包含在该类中。
2. 申明另一个类,继承该基类。
3. 实现一个返回基类函数指针的getInstance函数,即返回一个派生类实例的工厂方法。
4. 在外部代码中,通过多态机制访问该类。

dllExample.h:

#pragma once

 

#ifdef DLL_EXPORTS

#define DLL_API __declspec(dllexport)

#else

#define DLL_API __declspec(dllimport)

#endif

 

class DLL_API ExportInterface

{

public:

    virtual void foo() = 0;

};

 

extern "C" DLL_API ExportInterface*  getInstance();

 

#ifdef DLL_EXPORTS  //我们并不需要向外导出该类的定义,在外部代码编译时,也不需要包含此类的定义。

class ExportClass: public ExportInterface

{

pirvate:

    std::string x; //由于外部代码对此不可见,此处的std::string是安全的。

public:

    void foo(); //函数体在dllExample.cpp中实现

};

#endif

dllExample.cpp:

#define DLL_EXPORTS

#include "dllExample.h"

 

extern "C" DLL_API ExportInterface* getInstance()

{

    ExportInterface* pInstance = new ExportClass();

    return pInstance;

}

 

void ExportClass::foo()

{

    //do something...

    return;

}

 

 

调用约定

 

关于多个库的嵌套:

§   静态库包含:静态库或者动态库

           只需要对其它库的引用声明为extern即可,库的lib文件不会包含其它库的具体实现,主要在最终link的应用中包含其它库。

§   动态库包含 :静态、动态库

在本身库的地方应该包含静态库Lib,动态库的导入库lib,而后在最终调用本动态库的地方只需要引入这个库的导入即可。不过最终实现应该要有对应的动态库。

posted @ 2018-01-07 23:46  HEIS老妖  阅读(806)  评论(1编辑  收藏  举报