本文仅 供学习参考,欢迎提出 宝贵意见
一,同名称动态库加载顺序。
现有同名称动态库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)这样能解决(但是相对麻烦些了)。
以上为本人的一些测试结果,欢迎提出 不同意见