cvisual-studiomatlabdllmatlab-engine

Delay loading dll in release mode


In a C project i'm building in Visual Studio (C++ 2010 Express), I use the MatLab engine to allow for a user to provide a custom function to use within the project. The problem is that this code also needs to be able to run on computers without MatLab installed on it, meaning that the required DLL's will not be available on the computer in that case. Of course this should only work when the user does not try to access the piece of code which calls the matlab engine (I have provided a flag for this).

I have 3 dll's that are needed for this scenario.

So far i have been able to load the libeng.dll at run-time using LoadLibrary and GetProcAddress. The other two DLL's are a bit harder though, apart from the C-code calling the MatLab engine, the code is also often compiled as a mex-file (MatLab executable), to allow users to call it from MatLab. When compiling as a mex-file, both libmx.dll and libmex.dll are dynamically linked by the mex compiler. This means that using LoadLibrary and GetProcAddress don't work for these DLL's.

Right now I just add the libmx and libmex LIB's to the linker properties in visual studio and this works fine, but will not be possible for someone who doesn't have MatLab installed.

I have tried using delayLoad and this works if I compile in Debug mode, but gives this build error when I compile in release mode.

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

Is there a way to just completely skip looking for / Loading these DLL's if the part of the code that uses them is not accessed?

This is the command line for the linker:

/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 

Solution

  • The more I think about this, the more it looks like a [Wikipedia]: XY problem.

    1. The X (running the MEX file on a machine with no MATLAB libraries)

    According to [MathWorks]: Run MEX File You Receive from Someone Else (emphases are mine):

    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), which are free (I installed 3 of those versions to test this scenario), and also states:

    Run compiled MATLAB applications or components without installing MATLAB

    So, it's pretty clear (to me) that whoever would like to use that file, should install the MCR.

    2. The Y (using Delay Loaded DLLs)

    VStudio supports this feature ([MS.Docs]: Linker Support for Delay-Loaded DLLs) for quite some time.

    Never worked with MEX files, nor do I have the full problem specs, but allowing one such file to run when there are no MATLAB .dlls present, doesn't look like good design to me (meaning that it also contains other stuff - which on my opinion should be placed separately). The only scenario that makes sense is that the MEX file would be an .exe (don't know whether this is possible or it's just a dumb thing) and it would have some --help equivalent (which would be nice (but not mandatory) to run on environments without the .dll's).
    But that too could be solved using other ways (e.g. a README like file)

    3. The end problem

    Considering that there were / are multiple (logical) errors in the question:

    I can only conclude that for Release, "C:\Program Files (x86)\MATLAB\R2012a\bin\win32\libmx.dll" was incorrectly fed to the linker (instead of the corresponding .lib).

    I played a little bit with 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;
    }
    

    Notes:

    At the end, I would like to mention that MCR R2012a (and some others that were released after it), are built with VStudio 9.0 (2008), and building your program with VStudio 10.0 (2010), will yield having both CRT Libs in loaded your process, and in some cases that might trigger some errors (especially since VStudio 9.0's comes as an assembly).
    This applies to libmx.dll and libmex.dll, but not libeng.dll.