c++动态库加载顺序和同名动态库同时加载问题

 本文仅 供学习参考,欢迎提出 宝贵意见

一,同名称动态库加载顺序。  

现有同名称动态库Dllpath.dll 3个,内容非常简单,分别为

extern “C” __declspec(dllexport) void myPrint()
{
OutputDebugStringA(“exe path\n”);
}

extern “C” __declspec(dllexport) void myPrint()
{
OutputDebugStringA(“sys path\n”);
}

extern “C” __declspec(dllexport) void myPrint()
{
OutputDebugStringA(“SetDllDirectoryA path\n”);
}

将这3个dll分别放入exe path(Debug)下,系统目录(我选的是C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin)下,exe path下的新建的目录path下,来检测这3个dll谁会先加载。

main测试代码如下:

void test3()
{
	SetDllDirectoryA("D:\\work\\vs2010_project\\DllPathTest\\Debug\\path"); 
	HINSTANCE dllinstance2 = ::LoadLibrary(L"Dllpath.dll");
	if (dllinstance2)
	{
		typedef void (*PathPrint)();
		PathPrint pp = (PathPrint)GetProcAddress(dllinstance2, "myPrint");
		pp();
	}
}

int _tmain(int argc, _TCHAR* argv[])
{
	test3();
	getchar();
	return 0;
}

测试结果为:

打印出exe path。   如果删除exe pah下的该dll,那么打印出SetDllDirectoryA path。 如果再删除Debug\paht下的dll,那么才打印出sys path。

那么由结果可以得出,加载顺序优先级为:exe path > SetDllDirectory path > sys path

2,同名动态库同时加载问题。

在工作中有时候会碰到这样的问题,我一个工程项目需要同时引用多个第三方库(不同厂商SDK),先比如我有工程Demo,要引用两个厂家的sdk,厂家1的sdk内容为

(a.dll, b.dll , c.dll), 厂家2的sdk内容为(a.dll , d.dll, e.dll),注意,这里的两个a.dll 是不一样的,只是名字相同。那么怎么同时加载这两个厂家的sdk呢?

第一种尝试:同时放在exe path下,当然显然不行,覆盖了嘛。

第二种尝试:分别建两个目录,然后把两个厂家的sdk,分别放入两个目录下,然后动态加载(Loadlibrary),当然这里如果两个厂家的sdk太过复杂的话,可以将它们做一次封装。结果为:如果先加载厂家1的sdk,那么再加载厂家2的sdk的时候,加载厂家2的a.dll时候,(Loadlibrary)的返回值为加载厂家1的a.dll相同地址,也就是说,加载厂家2的a.dll是无效的,其实返回的是厂家1的a.dll,那么由此可以得出程序在加载dll的时候,如果加载 到有已经加载过的dll(名字相同),那么就不会重新加载,而是返回之前加载过的dll,(个人猜测,程序是有个dll加载列表的)。

第三种尝试:和第二种尝试几乎 一样,不同之处在于加载两个厂家sdk的时候,不使用动态加载,而是对两个厂家的sdk进行封装(成factory1.dll,  factory2.dll),这两个dll都是使用静态加载的方法去加载各自的 sdk,但是结果和第二种尝试是一样的。

第四种尝试:将两个厂家的sdk封装成com组件,测试结果同样为,先加载的组件有效,后加载的com组件无效。

第五中尝试:根据之前的 尝试,猜测程序是有dll加载列表的,所以只要我有同名的dll,无论怎么加载,后加载的dll都不会成功(返回先加载的dll)(如果有好的方法,请留言,非常感谢)。于是,只能采用进程间通信,(就是开进程加载各自的sdk)这样能解决(但是相对麻烦些了)。


以上为本人的一些测试结果,欢迎提出 不同意见

    原文作者:mincheat
    原文地址: https://blog.csdn.net/mincheat/article/details/51312173
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞