65.9K
CodeProject 正在变化。 阅读更多。
Home

延迟加载 DLL

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.43/5 (7投票s)

2003 年 1 月 12 日

2分钟阅读

viewsIcon

118263

downloadIcon

1014

一个易于使用的库,让您可以使用不同的编译器,为不同的处理器优化编译您的 DLL

引言

这是一个易于使用的库,让您可以使用不同的编译器,为不同的处理器优化编译您的 DLL。

详细说明

将所有要优化的类和函数移动到 DLL 中,然后 DelayLoader 库将自动从最快的(对于此处理器可用)DLL 中导入所有函数。

包括 4 个项目

  • DelayDLL,一个库项目,用于在您自己的工作区中使用
  • MainDLL,一个导出函数的示例 DLL
  • Test,一个导出函数的示例 DLL
  • MainMFC,一个使用上述项目的示例项目,没有花哨的 MessageBox,只需通过调试器逐步执行,即可查看加载了哪个 DLL。 完成一个 TRACE 输出,因此您可以轻松查看当前加载了哪个 DLL

该库基于 DLL 的延迟加载。 因此,我们在第一次需要 DLL 时开始加载它。 不需要调用 LoadLibraryGetProcAdress 函数,Microsoft 的延迟加载会处理这个问题。

通过一个特定的钩子机制,我们可以强制我们的应用程序加载一个与编译时编程不同的 DLL。 我们甚至可以获取不同命名函数的地址。 DelayDLL.dll 应该由 MainMFC 程序加载,但由于我们在我的 Athlon MP 上运行此程序,因此加载了 DelayDLL.Athlon.dll 文件。

当我们构建一个应该使用处理器特定优化的程序时,此钩子非常容易。 UnloadDelayedDLL( LPSTR ) 方法可以在运行时卸载 DLL,以释放内存,如果您没有像我一样有 1Gb 的 RAM :-p

希望这对您有所帮助。

如何使用

  • 将 DelayDll 项目添加到您的工作区。
  • 为您的项目设置对该项目的依赖关系,该库将自动链接到您的 exe。
    或者
    将预编译库 delaydll.lib 添加到您的 DLL 的配置中。
  • 将一个新文件添加到您的项目中,以便您可以轻松更改/添加新的 DLL(请参见下文。)
  • 复制配置
  • 构建->配置
  • 选择您要优化的 DLL 项目,

您只能添加 Win32 Release 的副本,并将其称为 w32 Athlon Rls。 或者也复制 win32 Debug,并将其称为 w32 Athlon Dbg。 您唯一需要在项目设置中更改的是,在链接选项卡上,输出名称,例如 MainDLL.Athlon.dll。

当然,您应该为这个配置选择另一个编译器(使用 Codeplay Compiler Controller 插件)。 或者自己制作一些汇编文件并将它们用于此配置。 目前仅使用 VectorC 编译 .c 文件,因此不包含整个项目。( 尚不支持 cpp)。 当然,您也可以使用 Intel 编译器来创建优化的 DLL。

这是一个要添加到您项目中的文件的示例,它将使用优化的 DLL。

// <START OF FILE : MyDelayDlls.cpp>
/******************************************************************/
/*         Sample .cpp file, to include in your executable        */
/******************************************************************/
#include "..\DelayDll\DelayDll.h"

// Tell delay loader to call my hook function
SET_DLIHOOK_PROC

/*****************************************/
/*Which DLLs should be Delay loaded  */
/***************************************/
// Use Upper and Lower case letters, exactly the same as in de DLL 
// Project ,Thanks to MS DelayLoader :-(
#pragma comment(linker, "/DelayLoad:Test.dll")
#pragma comment(linker, "/DelayLoad:MainDLL.dll")

// Descriptor for Test.dll
// value nr,Description
// 1InUse, always 1, for the last in line, use 0, so library known array 
//  is ended.
// 2DllName, use this if your optimized DLL has a complete 
// different name than your original DLL
// 3DllExtension, if you use an extension, Original:Test.dll, 
// Optimized:Test.Pentium.dll
// 4Optimized for Processor, A PIV dll, will not be loaded on a PIII
// 5Used Compiler, not used, but maybe we ever want to know this??

DLLDescriptor TestDLL[] = 
{
  1,NULL,"Pentium.dll",DELAYDLL_PROC_PENTIUM,DELAYDLL_COMP_INTEL,
  NULL
};

// Descriptor for another DLL
DLLDescriptor MainDLL[] = 
{
  1,"MainPIV.dll",NULL,DELAYDLL_PROC_PIV,DELAYDLL_COMP_VECTORC,
  1,NULL,"Athlon.dll",DELAYDLL_PROC_ATHLON,DELAYDLL_COMP_VECTORC,
  1,NULL,"PII.dll",DELAYDLL_PROC_PII,DELAYDLL_COMP_VECTORC,
  NULL
};


// Only these DelayLoaded DLL will be checked for there Optimized versions
// value nr,Description
// 1Dll name, (case sensitive)
// 2Use this Descriptor struct 
// ( All DLLs, could have the same Descriptor struct, 
// ONLY when Extensionname is 
//  used and not a fullname )

DLLCollection pDelayLoadedDLLs[] = 
{ 
  "Test.dll", TestDLL,   // Tries to load first : Test.Pentium.dll, then Test.dll
  "Test2.dll", TestDLL,  // Tries to load first : Test2.Pentium.dll, then Test2.dll
  "MainDLL.dll", MainDLL,// Tries to load first : MainPIV.dll, then MainDLL.Athlon.dll, 
                         // then MainDLL.PII.dll, then MainDLL.dll
  NULL
};
//<END  OF  FILE>
© . All rights reserved.