C++如何生成动态链接库,请查看之前的博客。本文主要讲解模板与动态链接库
1 模板与接口的矛盾之处
模板类,模板函数必须将声明和定义都放在.h文件里(否则调用失败,会显示无法解析的外部符号)。因此模板类型是不确定的,是不支持.h.cpp文件分离式编译的。但是如果又不想暴露实现代码,又想实现轻量级模板通用代码,那么需要怎么办呢?这就是今天要讨论的问题。(动态库生成,调用请查看之前博客)
2模板类动态库导出
新建一个template_dll_test工程,在属性表,将配置类型改成动态库,c+±>预处理器中添加“TEMPLATE_DLL_TEST_EXPORTS”
首先定义一个模板类,分开写.h和.cpp文件:
//.h文件
#pragma once
//添加导出宏定义
#ifdef TEMPLATE_DLL_TEST_EXPORTS
#define TEMPLATE_DLL_API __declspec(dllexport)
#else
#define TEMPLATE_DLL_API __declspec(dllimport)
#endif
#include<iostream>
template<typename T>
//这里不用添加导出符号,注意与普通类的区别(非模板类这里要添加导出符号)
class TemplateBase
{
public:
TemplateBase();
~TemplateBase();
T add_num(T a, T b);
};
cpp文件
#include "TemplateBase.h"
//在cpp文件中告诉编译器导出实例化之后的类,必须实例化才行
template class TEMPLATE_DLL_API TemplateBase<double>;
template<typename T>
TemplateBase<T>::TemplateBase()
{
}
template<typename T>
TemplateBase<T>::~TemplateBase()
{
}
template<typename T>
T TemplateBase<T>::add_num(T a, T b)
{
std::cout << "templateBase::add_num" << std::endl;
return T(a+b);
}
点击工程,右键生成,即可生成dll,lib文件。
最后,调用一下,看看是否成功:
新建一个控制台工程,调用刚才生成的动态库(具体调用可以看之前的博客)
#include"TemplateBase.h"
int main()
{
TemplateBase<double>tb;
tb.add_num(3.0, 2.0);
std::cout << "hello world" << std::endl;
}
调用成功了。
2模板函数的类导出动态库
有时候可能不需要整个类都为模板,而是某几个函数为模板即可。定义一个这样的类:
.h文件
#pragma once
#ifdef TEMPLATE_DLL_TEST_EXPORTS
#define TEMPLATE_DLL_API __declspec(dllexport)
#else
#define TEMPLATE_DLL_API __declspec(dllimport)
#endif
#include<iostream>
class TEMPLATE_DLL_API TemFunBase
{
public:
TemFunBase()=default;
~TemFunBase()=default;
template <typename T>
T add_num(T a, T b);
};
.cpp文件
#include "TemFunBase.h"
//注意这里与导出类的区别
template TEMPLATE_DLL_API double TemFunBase::add_num<double>(double, double);
template<typename T>
T TemFunBase::add_num(T a, T b)
{
std::cout << "TemFunBase::add_num" << std::endl;
return T(a + b);
}
按照模板类导出时,同样配置属性表,右键生成,就会生成dll和lib文件
调用模板函数的dll:新建控制台工程,属性表添加必要的文件头、dll路径,lib文件,在main函数中调用:
#include<iostream>
#include"TemFunBase.h"
int main()
{
TemFunBase tfb;
tfb.add_num(3.0, 2.0);
std::cout << "hello world" << std::endl;
}