在发布模式下延迟加载dll

Delay loading dll in release mode

在我用 Visual Studio (C++ 2010 Express) 构建的 C 项目中,我使用 MatLab 引擎允许用户提供自定义函数以在项目中使用。问题是此代码还需要能够在未安装 MatLab 的计算机上 运行 ,这意味着在这种情况下所需的 DLL 在计算机上将不可用。当然,这应该只有在用户不尝试访问调用 matlab 引擎的代码段时才有效(我为此提供了一个标志)。

这个场景需要 3 个 dll。

到目前为止,我已经能够使用 LoadLibraryGetProcAddress[=38= 在 运行 时加载 libeng.dll ]. 其他两个 DLL 有点难,除了调用 MatLab 引擎的 C 代码外,代码也经常被编译为 mex 文件(MatLab 可执行文件),以允许用户从 MatLab 调用它。当编译为 mex 文件时,libmx.dll 和 libmex.dll 都由 mex 编译器动态链接。这意味着使用 LoadLibraryGetProcAddress 不适用于这些 DLL。

现在我只是将 libmx 和 libmex LIB 添加到 visual studio 的链接器属性中,这工作正常,但对于没有安装 MatLab 的人来说是不可能的。

我已经尝试使用 delayLoad,如果我在调试模式下编译,这会起作用,但在发布模式下编译时会出现此构建错误。

1>C:\Program Files (x86)\MATLAB\R2012a\bin\win32\libmx.dll : fatal error LNK1107: invalid or corrupt file: cannot read at 0x2B8

如果使用这些 DLL 的代码部分未被访问,有没有办法完全跳过查找/加载这些 DLL?

这是链接器的命令行:

/OUT:"C:\Users\A.Vandenber\documents\visual studio 2010\Projects\Flash\Release\Flash.exe" /NOLOGO "C:\Program Files (x86)\MATLAB\R2012a\bin\win32\libmx.lib" "C:\Program Files (x86)\MATLAB\R2012a\bin\win32\libmex.lib" "kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "odbc32.lib" "odbccp32.lib" /DELAYLOAD:"libmex.dll" /DELAYLOAD:"libmx.dll" /MANIFEST /ManifestFile:"Release\Flash.exe.intermediate.manifest" /ALLOWISOLATION /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG /PDB:"C:\Users\A.Vandenber\documents\visual studio 2010\Projects\Flash\Release\Flash.pdb" /OPT:REF /OPT:ICF /PGD:"C:\Users\A.Vandenber\documents\visual studio 2010\Projects\Flash\Release\Flash.pgd" /LTCG /TLBID:1 /DYNAMICBASE /NXCOMPAT /MACHINE:X86 /ERRORREPORT:QUEUE 

首先,将您的代码移至包含 access privileges 而不是 read-only 的目录。也在这里检查这个答案:Delay load DLL

要将 dll 文件添加到 Visual Studio,您可以按照此 Linking dll in Visual Studio

另一个建议是将 dll 放在 c:\windows\system32 中。当一个程序 运行s 时,它会在 c:\windows\system32 目录中搜索这个文件。在此之前,它将搜索程序所在的目录运行。 Visual Studio 运行s 项目目录中的程序(如果提到的 .dll 文件未放在 windows\system32 目录中,则应放在该目录中)。同样,如果程序的可执行文件是运行手动从其目录中获取的,则上述.dll文件应该在same folder where the program's executable文件所在的位置。您将需要管理员权限才能执行此操作。

越想越像[Wikipedia]: XY problem.

1。 X(运行在没有 MATLAB 库的机器上安装 MEX 文件)

根据[MathWorks]: Run MEX File You Receive from Someone Else重点是我的):

On Windows® platforms, install the C++ compiler run-time libraries used to create the MEX file.

...

A MEX file is a dynamically linked subroutine that the MATLAB interpreter loads and executes when you call the function. Dynamic linking means that when you call the function, the program looks for dependent libraries. MEX files use MATLAB run-time libraries and language-specific libraries. A MEX file might also use specialized run-time libraries. The code for these libraries is not included in the MEX file; the libraries must be present on your computer when you run the MEX file.

[MathWorks]: MATLAB Runtime contains links for downloading many versions (yours - according to your paths - would be [MathWorks]: MCR Runtime - MCR_R2012a_win32_installer.exe),它们是 免费的(我安装了其中的 3 个版本来测试这种情况),并且还指出:

Run compiled MATLAB applications or components without installing MATLAB

所以,(对我而言)很清楚,无论谁想要使用该文件,都应该安装 MCR.

2。 Y(使用延迟加载的DLLs)

VStudio 支持此功能 ([MS.Docs]: Linker Support for Delay-Loaded DLLs) 已有一段时间了。

从未使用过 MEX 文件,我也没有完整的问题规范,但在没有 时允许一个这样的文件 运行 MATLAB .dlls present,在我看来不是好的设计(这意味着它还包含其他东西——我认为应该单独放置)。唯一有意义的场景是 MEX 文件将是一个 .exe (不知道这是否可能或者它只是一个愚蠢的thing) 并且在没有 .dll 的环境中,它会有一些 --help 等效项(这很好(但 不是 强制性)到 运行 的)。
但这也可以通过其他方式解决(例如 README 之类的文件)

3。最终问题

考虑到问题中有/多个(逻辑)错误:

  • .dll传递给链接器
  • .lib 文件位于 bin 目录
  • 最新路径(extern/lib/win64/microsoft)包含64位 .lib s,而链接器设置为 32 位 输出
  • [MS.Docs]: Linker Tools Error LNK1107 很清楚(如问题中的错误信息)

我只能得出结论,对于 Release,“C:\Program Files (x86)\MATLAB\R2012a\bin\win32\libmx.dll" 被错误地馈送到链接器(而不是相应的 .lib)。

我玩了一点 MEX:

code.c:

#include <stdio.h>
#include <conio.h>
#include <mex.h>


int main(int argc, char **argv) {
    if (argc > 1) {
        fprintf(stdout, "Argument passed: mexEvalString() returns\n", mexEvalString("n = 1;"));
    } else {
        fprintf(stdout, "Argument NOT passed: pass...\n");
    }
    fprintf(stdout, "Press a key to exit...\n");
    _getch();
    return 0;
}

备注:

  • 我用了fprintf因为在mex.h中有一行:

    #define printf mexPrintf
    
  • 不知道要使用libmx.dll中的什么函数来强制直接添加它(不仅仅是[=54的依赖项) =]libmex.dll)

  • 我能够在DebugRelease(当没有传递 arg 时,程序 运行 没有添加 MEX .dlls %PATH%)。
    确实在 运行 时我遇到了 访问冲突 ,但那是一个完全不同的问题
  • 不用说,将任何 .dll 添加到“Linker -> Input -> Additional Dependencies”,触发了完全相同的错误

最后,我想提一下 MCR R2012a(以及之后发布的其他一些)是使用 VStudio 9.0 (2008),并使用 VStudio 10.0 (2010) 构建您的程序,将同时拥有 CRT Libs 加载了您的进程,在某些情况下可能会触发一些错误(特别是因为 VStudio 9.0 作为 assembly ).
这适用于 libmx.dlllibmex.dll,但不适用于 libeng.dll.