Windows DLL

2019年8月14日 0 条评论 100 次阅读 0 人点赞

动态链接库的编写

编写DLL时,在需要导出给别的程序用的名称前加上```__declspec(dllexport),而在别的程序使用dll中名称时,对于普通名称可以直接使用,而对于含有静态成员的类时,则会出现链接器找不到类中的静态成员的错误,这时则需要使用__declspec(dllimport)` 表明该类中的静态成员定义在DLL中。我们可以用一个宏定义来简化:

#define DLL_EXPORT

#ifdef DLL_EXPORT
#define DLL_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)
#endif // DLL_EXPORT

在DLL的工程中定义DLL_EXPORT宏,并且在需要导出的名称前加上DLL_API,而在提供给用户的头文件中定义DLL_IMPORT

函数

// 头文件 testdll.h
DLL_API std::shared_ptr<InterFace_B> getInstance();

// 实现文件 testdll.cpp
#include "testdll.h"
std::shared_ptr<InterFace_B> getInstance()
{
	return std::shared_ptr<InterFace_B>(new B());
}

全局变量

// testdll.h
extern int DLL_API global;

// testdll.cpp
int global;

类里面如果有静态成员,则调用时必须使用__declspec(dllimport),否则会找不到静态成员

// testdll.h
class DLL_API A
{
public:
	static int count;
	static int sum(int a, int b);
	void print(int x);
};

// testdll.cpp
int A::count = 0;

int A::sum(int a, int b)
{
	return a + b;
}

编写DLL中的类时还有一个问题,就是如果其中包含了STL等取决于编译器实现的东西,比如一个string。当编写使用这个DLL的客户端程序时,包含DLL配套头文件后声明这个类的对象,对象中所使用的是当前编译器的string实现,而类的成员函数的实现是在DLL中的,它所使用的string实现是编写DLL时所使用的编译器的string实现。如果两者不同,就会产生错误。

解决方式是使用只包含C++基础类型(不取决与编译器实现的类型)的抽象基类和一个工厂方法, 那些取决于编译器实现的东西都放到抽象基类的派生类中,而这个派生类不导出,而工厂方法则构造一个派生类返回一个基类指针,这样用户可以使用这个基类指针调用派生类中的虚函数(多态特性),这样相当于统一使用DLL编译时编译器的实现:

// testdll.h
class DLL_API InterFace_B
{
public:
	std::string name;
	virtual const std::string& getName() const = 0;
	virtual void setName(const std::string&) = 0;
};

#ifdef DLL_EXPORT
class B :public InterFace_B
{
public:
	const std::string& getName() const override
	{
		return name;
	}
	void setName(const std::string& name) override
	{
		this->name = name;
	}
};
#endif // DLL_EXPORT

DLL_API std::shared_ptr<InterFace_B> getInstance();

// testdll.cpp
std::shared_ptr<InterFace_B> getInstance()
{
	return std::shared_ptr<InterFace_B>(new B());
}

动态库的调用

  1. 将DLL头文件中的#define DLL_EXPORT改为#define DLL_IMPORT,包含进需要调用DLL的工程中(#include "../include/testdll.h"
  2. 将DLL对应的lib文件也包含进来(右键资源文件add,或者#pragma comment(lib, "../lib/A.lib")
  3. dll文件放到生成的可执行文件所在的文件夹中

litmxs

这个人太懒什么东西都没留下

文章评论(0)