在可执行文件中使用嵌入式 .dll

Poj*_*ojo 2 c++ dll fmod visual-c++

好的。所以我知道有很多关于如何在 exe 中嵌入 dll 的问题,但我的问题是相当不同的。(具体来说,我正在使用 fmod 库在我的程序中播放声音,并且我正在嵌入 fmod.dll,但这不是重点。)

我使用的是 Visual C++ 2010 Ultimate。我已成功将 .dll 嵌入到 .exe 中。我的 resources.h 文件包含

#define IDR_DLL1  144
Run Code Online (Sandbox Code Playgroud)

我的 .rc 文件包含

IDR_DLL1  DLL  MOVEABLE PURE  "data\\fmod.dll"
Run Code Online (Sandbox Code Playgroud)

我的代码中有以下函数(我完全从另一个 stackoverflow 问题中窃取了它):

bool extractResource(const HINSTANCE hInstance, WORD resourceID, LPCTSTR szFilename)
{
bool bSuccess = false; 
try
{
    // Find and load the resource
    HRSRC hResource = FindResource(hInstance, MAKEINTRESOURCE(resourceID), L"DLL");
    HGLOBAL hFileResource = LoadResource(hInstance, hResource);

    // Open and map this to a disk file
    LPVOID lpFile = LockResource(hFileResource);
    DWORD dwSize = SizeofResource(hInstance, hResource);            

    // Open the file and filemap
    HANDLE hFile = CreateFile(szFilename, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    HANDLE hFileMap = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, dwSize, NULL);            
    LPVOID lpAddress = MapViewOfFile(hFileMap, FILE_MAP_WRITE, 0, 0, 0);            

    // Write the file
    CopyMemory(lpAddress, lpFile, dwSize);            

    // Un-map the file and close the handles
    UnmapViewOfFile(lpAddress);
    CloseHandle(hFileMap);
    CloseHandle(hFile);
    bSuccess = true;
}
catch(...)
{
    // Whatever
} 
return bSuccess;
}
Run Code Online (Sandbox Code Playgroud)

然后,我首先在 WinMain 函数中调用以下代码:

int WINAPI WinMain(HINSTANCE h1, HINSTANCE h2, LPSTR l, int a)
{
    extractResource(h1, IDR_DLL1, L"fmod.dll");
    /* etc */
}
Run Code Online (Sandbox Code Playgroud)

有用。它成功地提取出嵌入的 fmod.dll 的内容,并将其保存为同一目录中的文件......只有......当事先已经有一个 fmod.dll 时。如果 fmod.dll 不存在,我只会收到一条弹出消息,上面写着

The program can't start because fmod.dll is missing from your computer. Try reinstalling the program to fix this problem.
Run Code Online (Sandbox Code Playgroud)

...换句话说,我只能覆盖已经存在的 fmod.dll。例如,如果我改为将代码更改为

extractResource(h1, IDR_DLL1, L"fmod2.dll");
Run Code Online (Sandbox Code Playgroud)

它将写出完全相同的文件,具有完全相同的内容,标题为 fmod2.dll。到时候我可以去掉原来的fmod.dll,把新创建的fmod2.dll重命名为fmod.dll,就可以了。

   

很明显,问题在于它甚至在到达我的程序的入口点之前寻找 fmod.dll 的存在。在需要实际使用任何 fmod 内容之前,我的程序甚至无法执行任何代码。这似乎……非常不公平。那么即使能够嵌入 dll 又有什么意义呢?

那么,我的问题是

  1. 是否可以直接从 .exe 内部使用 .dll,而无需将其解压缩为文件?(我的首选方法)

  2. 如果 1.) 是不可能的,那么在检查文件是否存在之前,我如何至少修改我的代码以写出文件?

Poj*_*ojo 5

嗯,解决方案出奇的简单。我只是遵循了DyP关于延迟加载 dll的建议

我只是在我的项目属性中添加了一件事,如下所示:

就是这样!

当编程问题有简单的解决方案时,我喜欢它。:)

  • 它可能是您的解决方案,但不是问题的答案。延迟加载迟早会变成*真正的*加载。那么克拉布姆。 (2认同)