动态链接库导出模板类以及一些问题

这篇文章先说如何写一个导出模板类的动态链接库,再说问题。

要编写自己的动态链接库首先需要创建一个dll工程,我用的是win10+vs2015


创建dll工程后vs会自动给你生成几个文件。在Dll2.h和Dll2.cpp中写自己的类定义和类函数实现就好了。但是因为是要导出类所以要有__declspec(dllexport)又因为是模板所以直接上代码看看怎么做吧

.h

#pragma once
#include 
#include 
#include 



#ifdef _EXPORTS
#define _USE_DLL_ __declspec(dllexport)//用于导出声明
#else 
#define _USE_DLL_ __declspec(dllimport)//用于导入声明
#endif

template< class TYPE>//模板声明
class _USE_DLL_ CTest
{
public:
	TYPE add(TYPE a, TYPE b);
	TYPE red(TYPE a ,TYPE b);
};
template  _USE_DLL_ CTest* Get();



.cpp

#include "pch.h"
#define _EXPORTS//这句要加在#include "pch.h"之前,用于导出。
#include "Dll1.h"
template
TYPE CTest::add(TYPE a,TYPE b)
{
	return a+b;
}
template
TYPE CTest::red(TYPE a,TYPE b)
{
	return a-b;
}
template
_USE_DLL_ CTest*  Get()
{
	CTest instance=new CTest();
	return instance;
}
void createcode()//生成代码
{
	CTest* f_pTest= Get();
	f_pTest->add(1.2,1.5);
	f_pTest->red(1.9,1.5);
}
从上面的代码看导出模板类(一不小心赠送了一个模板函数)没什么贴别之处,除了加上了导出生命和模板声明之外最不同也是最关键的地方就是多了一个“没用“的函数createcode()。这个函数之所以存在是和模板息息相关的。模板在不实例化(使用)的时候是不生成代码的,这样的话我们写的CTetst模板类和Get()模板函数都只是一个空。因为在dll内部他们并没有被使用,所以不会产生相关代码。而有了createcode()这个“没用”的函数,编译器编译Createcode的时候知道了createcode需要使用CTest以及函数add和red,还有Get(),所以编译器生成了float版本的代码。也就是说目前这个dll只支持CTest模板类对float的实例化,如果要想支持int,则createcode函数里要加上相应的int相关代码。是不是感觉很坑?没办法,能导出就不错了!返回来,也就说这个”没用”的函数并不是没有用处只是没有使用,不仅有用而且还是导出模板的关键所在。
下面就是要说封装dll过程中遇到的问题了
问题1:应用程序无法正常启动(0xc000a200).


最开始在网上查都说是dll位数不对 什么32位机器用的64位dll吧啦吧啦。其实并不是,最终的解决的办法是在dll项目属性中连接器的命令设置中增加了一条 /APPCONTAINER :NO 命令。然后重新生成dll。就不会包这个问题了。然而出现了新的问题




问题2:运行时提示自己缺少VCRUNTIME14D_APP.DLL这个问题好诡异,自己用depandency walker看了dll内部依赖,确实少这个dll。前面的名字是系统的dll,但是后面却多了一个“_APP”。而且我找了确实找不到这个dll 但是在 C:\Windows\SysWOW64目录下找到了VCRUNTIME14D.DLL,思考了良久有个群友说让我把这个重命名成VCRUNTIME14D_APP.DLL结果又提示VCRUNTIME14D.DLL找不到了。于是复制了一份VCRUNTIME14D.DLL,然后将副本重命名为VCRUNTIME14D_APP.DLL再重新运行居然正常运行了,好吧我承认我很山寨,但是不管怎么说可以运行了。至于为什么出现这些问题以及为什么这样能解决。有时间在深究吧。


针对以上两个问题有了正确的解决方案。问题1和问题2产生的原因根本原因是dll和客户端程序“不匹配”。dll工程是 Universal Windows的而我的客户端是win32的。win32工程 的意思是传统的windows程序,而Universal Windows指的是UWP程序,这种程序是微软跨平台程序也就是PC,平板,手机,Xbox等其他win0系统设备上的通用程序。这种程序默认是在沙盒中运行的,因此也就有了问题一的出现,也就解释了为什么/APPCONTAINER :NO命令可以“解决”问题一,

沙盒程序使用的dll,是存在于沙盒中名字为xxx_app.dll的动态链接库,这又解释了问题2。所以以上两个问题的根本原因是客户端和dll的项目类型“不匹配”造成的。

 
 

你可能感兴趣的:(c++,动态链接库)