Search code examples
c++matlabvisual-studio-2013shared-librariesmcc

Unresolved symbol while using a matlab function turned into a shared library


I'm using MATLAB R2012A and Visual Studio 2013.

I have a simple function in a simulation.m file.

function [ r ] = simulation(  )
  r = 42;
end

Since VS2013 is not supported by MATLAB 2012 I've setup my version of VS in MATLAB using these files. I've then built the corresponding dll using:

>> mcc -v -W lib:libsim -T link:lib simulation.m
Compiler version: 4.17 (R2012a) 
Processing C:\Program Files\MATLAB\R2012a\toolbox\matlab\mcc.enc 
Processing include files... 
2 item(s) added. 
Processing directories installed with MCR... 
The file mccExcludedFiles.log contains a list of functions excluded from the CTF archive. 
1 item(s) added. 
Generating MATLAB path for the compiled application... 
Created 41 path items. 
Begin validation of MEX files: Wed Apr 15 13:55:43 2015 
End validation of MEX files: Wed Apr 15 13:55:43 2015 
Parsing file "C:\Users\aaptel\Documents\MATLAB\simulation.m" 
    (Referenced from: "Compiler Command Line"). 
Parsing file "C:\Program Files\MATLAB\R2012a\toolbox\compiler\deploy\deployprint.m" 
    (Referenced from: "Compiler Command Line"). 
Parsing file "C:\Program Files\MATLAB\R2012a\toolbox\compiler\deploy\printdlg.m" 
    (Referenced from: "Compiler Command Line"). 
Deleting 0 temporary MEX authorization files. 
Generating file "libsim.h". 
Generating file "libsim.c". 
Generating file "libsim.exports". 
Generating file "C:\Users\aaptel\Documents\MATLAB\readme.txt". 
Executing command: ""C:\Program Files\MATLAB\R2012a\bin\mbuild"  -O -v -output "libsim" "libsim.c" "libsim.exports" -link shared"-> Default options filename found in C:\Users\aaptel\AppData\Roaming\MathWorks\MATLAB\R2012a 
---------------------------------------------------------------- 
->    Options file           = C:\Users\aaptel\AppData\Roaming\MathWorks\MATLAB\R2012a\compopts.bat 
->    COMPILER               = cl 
->    Compiler flags: 
         COMPFLAGS           = -MD -c -Zp8 -GR -EHsc- -Zc:wchar_t- -W3 -nologo -I"C:\PROGRA~1\MATLAB\R2012a\extern\include\win64" -DMSVC -DIBMPC /D_CRT_SECURE_NO_DEPRECATE 
         OPTIMFLAGS          = -O2 -DNDEBUG 
         DEBUGFLAGS          = -Z7 
         arguments           =  
         Name switch         = /Fo 
->    Pre-linking commands   =  
->    LINKER                 = link 
->    Link directives: 
         LINKFLAGS           =  /MACHINE:AMD64 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /LIBPATH:"C:\PROGRA~1\MATLAB\R2012a\extern\lib\win64\microsoft" /nologo /manifest /manifestfile:"libsim.msvc.manifest" mclmcrrt.lib   /dll /implib:"libsim.lib" /def:"C:\Users\aaptel\AppData\Local\Temp\mbuild_F85T7Q\templib.def" 
         LINKFLAGSPOST       =  
         Name directive      = /out:"libsim.dll" 
         File link directive =  
         Lib. link directive =  
         Rsp file indicator  = @ 
->    Resource Compiler      = rc /fo ".res" 
->    Resource Linker        =  
---------------------------------------------------------------- 


--> cl  -MD -c -Zp8 -GR -EHsc- -Zc:wchar_t- -W3 -nologo -I"C:\PROGRA~1\MATLAB\R2012a\extern\include\win64" -DMSVC -DIBMPC /D_CRT_SECURE_NO_DEPRECATE /FoC:\Users\aaptel\AppData\Local\Temp\mbuild_F85T7Q\libsim.obj -IC:\PROGRA~1\MATLAB\R2012a\extern\include -IC:\PROGRA~1\MATLAB\R2012a\simulink\include -O2 -DNDEBUG libsim.c 

libsim.c 

--> type C:\Users\aaptel\AppData\Local\Temp\mbuild_F85T7Q\mbuild_tmp.exports | "C:\PROGRA~1\MATLAB\R2012a\sys\perl\win32\bin\perl.exe" -e "print \"LIBRARY libsim.dll\nEXPORTS\n\"; while (<>) {print;}" > "C:\Users\aaptel\AppData\Local\Temp\mbuild_F85T7Q\templib.def" 

    Contents of C:\Users\aaptel\AppData\Local\Temp\mbuild_F85T7Q\mbuild_tmp.rsp: 
  C:\Users\aaptel\AppData\Local\Temp\mbuild_F85T7Q\libsim.obj 


--> link /out:"libsim.dll"  /MACHINE:AMD64 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /LIBPATH:"C:\PROGRA~1\MATLAB\R2012a\extern\lib\win64\microsoft" /nologo /manifest /manifestfile:"libsim.msvc.manifest" mclmcrrt.lib   /dll /implib:"libsim.lib" /def:"C:\Users\aaptel\AppData\Local\Temp\mbuild_F85T7Q\templib.def"  @C:\Users\aaptel\AppData\Local\Temp\mbuild_F85T7Q\mbuild_tmp.rsp   

   Création de la bibliothèque libsim.lib et de l'objet libsim.exp 

--> "if exist C:\Users\aaptel\AppData\Local\Temp\mbuild_F85T7Q\templib.def del C:\Users\aaptel\AppData\Local\Temp\mbuild_F85T7Q\templib.def" 


--> mt.exe -outputresource:"libsim.dll";2 -manifest "libsim.msvc.manifest" 

Microsoft (R) Manifest Tool version 6.3.9600.17298  
Copyright (c) Microsoft Corporation 2012.   
All rights reserved.  

--> del "libsim.msvc.manifest"

I now have the following files:

  • libsim.dll
  • libsum.exp
  • libsim.c
  • libsim.exports
  • libsim.h

I've installed the 64bit MATLAB runtime for MATLAB R2012a.

I've created a new C++ solution in VS and added the libsim.lib dependency, along with the matlab lib/include dir.

Here is my main cpp file:

#include <cstdio>
#include <libsim.h>

int main(void)
{
    double v = 42;
    libsimInitialize();
    printf("%d\n", v);
    libsimTerminate();
    return 0;
}

The compiler flags:

/GS /analyze- /W3 /Zc:wchar_t /I"C:\Users\aaptel\Documents\Visual Studio 2013\Projects\CppTest\CppTest\Include\matlab" /ZI /Gm /Od /sdl /Fd"Debug\vc120.pdb" /fp:precise /D "_MBCS" /errorReport:prompt /WX- /Zc:forScope /RTC1 /Gd /Oy- /MDd /Fa"Debug\" /EHsc /nologo /Fo"Debug\" /Fp"Debug\CppTest.pch" 

The linker flags:

/OUT:"C:\Users\aaptel\Documents\Visual Studio 2013\Projects\CppTest\Debug\CppTest.exe" /MANIFEST /NXCOMPAT /PDB:"C:\Users\aaptel\Documents\Visual Studio 2013\Projects\CppTest\Debug\CppTest.pdb" /DYNAMICBASE "kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "odbc32.lib" "odbccp32.lib" "libsim.lib" /DEBUG /MACHINE:X86 /INCREMENTAL /PGD:"C:\Users\aaptel\Documents\Visual Studio 2013\Projects\CppTest\Debug\CppTest.pgd" /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /ManifestFile:"Debug\CppTest.exe.intermediate.manifest" /ERRORREPORT:PROMPT /NOLOGO /LIBPATH:"C:\Users\aaptel\Documents\Visual Studio 2013\Projects\CppTest\CppTest\Lib\matlab" /TLBID:1

libsim.lib is in there, the Lib\matlab and Include\matlab paths have a copy of the matlab runtime libs and headers.

But. it. doesn't. freaking. compile.

1>Source.obj : error LNK2019: symbole externe non résolu _libsimInitialize référencé dans la fonction _main
1>Source.obj : error LNK2019: symbole externe non résolu _libsimTerminate référencé dans la fonction _main
1>C:\Users\aaptel\Documents\Visual Studio 2013\Projects\CppTest\Debug\CppTest.exe : fatal error LNK1120: 2 externes non résolus

Notice how the compiler looks for the symbol prefixed with an underscore. If you look at the symbol in the lib file using DUMPBIN you can see that they don't have the prefix (full DUMPBIN output):

Dump of file libsim.lib

File Type: LIBRARY

Archive member name at 8: /               
552CE345 time/date Tue Apr 14 11:52:05 2015
         uid
         gid
       0 mode
     190 size
correct header end

    15 public symbols

      3AA __IMPORT_DESCRIPTOR_libsim
      5D0 __NULL_IMPORT_DESCRIPTOR
      706 libsim_NULL_THUNK_DATA
      85E __imp_libsimInitialize
      85E libsimInitialize
      8CA __imp_libsimInitializeWithHandlers
      8CA libsimInitializeWithHandlers
      9B4 __imp_libsimTerminate
      9B4 libsimTerminate
      942 __imp_libsimPrintStackTrace
      942 libsimPrintStackTrace
      A8A __imp_mlxSimulation
      A8A mlxSimulation
      A20 __imp_mlfSimulation
      A20 mlfSimulation

Why doesn't it work and how do I call my matlab function from C++?


Solution

  • OK, turns out the VS project was 32bit but the lib/dll generated by MATLAB was 64bit. By switching the VS project to x64, it compiled.

    VS seems to silently ignore linking 32bit executable against 64bits libs

    Also see follow-up post on the mathworks QA site:

    http://www.mathworks.com/matlabcentral/answers/203699-how-do-i-call-standalone-matlab-shared-library-built-with-mcc-from-c