西北望长安,可怜无数山
------------------------------------------------------
windows开发中,为了不想把exe和一堆dll放在一起,勤劳的程序员们使用了很多方法。这里罗列一下。
- 将dll拷贝到windows目录或system32目录中。方法可行。
挑剔的朋友不想干了,这不够绿色。不想“污染”系统盘。 - 手动添加系统环境变量。打开“系统”属性,添加dll目录到“PATH”系统变量(或用户变量)。测试方法可行。
程序员们很善良,不想给用户增加麻烦。 - 把方法2改成简单自动点。写一个bat或者再写简单exe只做上面的事。注册一下PATH变量。
程序员们很善良,不想添加PATH变量,而且觉得再写一个bat或exe,不是很友好。 - 使用显示加载dll方式,动态加载dll。方法当然可行。
程序会在需要的时候才去加载DLL文件,先获取到DLL文件中相关的函数入口地址,然后转换执行,执行完之后可以立即释放掉资源。显示加载具有更好的灵活性,能更加有效的使用内存,在编写大型程序时往往使用显示加载方式(如下)。
可是这样要自己实现加载dll、地址类型转换、卸载dll。好不累人。懒惰的程序员已经习惯了导入lib,include头文件了。typedef int (*test) (int a, int b); int main(int argc,char *argv[]) { HMODULE hDll=LoadLibrary(L"DllTest.dll"); if(hDll!=NULL) { test sub=(SubFunc)GetProcAddress(hDll,"test"); ... system("pause"); } FreeLibrary(hDll); return 0; }
有没有一种更爽一点的方式呢?
-
程序员尝试把dll放到别的目录,在main函数中先调用setDllDirectory修改dll路径。该方法对于动态加载的dll有效。
对于隐式加载的dll。程序一开始就报找不到dll,或者直接奔溃退出了。
隐式调用的情况下似乎程序员没有更好的方式控制DLL的目录? -
VC++开发中,其实已经提供了一种延迟加载的隐式引用DLL编译技术。内部原理其实是使用了显示调用dll的方法。只是编译器和IDE帮程序员做了很多工作。
首先要设置VC项目中的连接器-输入。把引用的dll改为延迟加载。也不是所有的dll都要写,很多时候,只需要把入口dll的名称写进来就可以了。
-------------------------------------------- 蓦然回首,那人却在灯火阑珊处----------------------------------------------------
看起来解决了问题!很多项目能成功跑起来,有些项目缺跑成功。这是为什么呢?
深层原因是方法6虽然使用了隐式加载dll的方式,但是其实内部采用的显示加载(调用LoadLibrary)技术。程序中如果使用了全局变量类型,就会导致发生程序启动异常。因为全局变量,在还没有调用动态加载dll时就已经触发了。此时的dll还未找到。
因此。我们需要代码上做一些改动,有时候只需要改动一点点(具体情况具体分析)。将该全局变量,改为指针类型。在窗口或程序开始的地方。先动态设置临时PATH变量,或调用setDllDirectory指定dll目录后,再动态实例化指针对象。
//修改PATH临时变量
SetPrivatePathEnvironment();
//动态加载dll中方法或对象类型。m_Motion为指针变量
m_Motion = CMotion::CreateCMotion(m_MotionType);
这样,您的exe就可以脱离一堆dll的包围。看起来简洁舒爽。也不需要用户先执行bat或修改环境变量了。
来源:CSDN
作者:zj53hao
链接:https://blog.csdn.net/zj53hao/article/details/103570146