Calling MATLAB from C ++ Errors: Unresolved External Character

I am facing several errors when calling MATLAB function from C ++. The main idea: first compile the MATLAB function and generate the DLL file, and then include the .h and .lib files in C ++. Finally, write .cpp to test and call the function. Here are my detailed steps and please tell me where I am going wrong.

(Using MATLAB 2012b and Visual C ++ 2008, Windows 7 64-bit)

In MATLAB:

  • mbuild -setup and mex -setup to install Visual Microsoft Visual C ++ 2008 SP1 as a compiler.
  • Create MyAdd.m in the folder C:\Users\WangYudong\Documents\MATLAB\MyAdd_M , and the function will look like this:

     function [c] = MyAdd(a, b) c = a + b; 
  • mcc -W cpplib:libMyAdd -T link:lib MyAdd to compile MyAdd.m and generate several files, including libMyAdd.dll , libMyAdd.h , libMyAdd.lib and other files.

In c ++

  • Select VC ++ DirectoriesInclude Files to add E:\MATLAB\R2012b\extern\include .

  • Select VC ++ DirectoriesLibrary Files to add E:\MATLAB\R2012b\extern\lib\win64\microsoft and C:\Users\WangYudong\Documents\MATLAB\MyAdd_M .

  • Choose LinkerEnterAdditional dependencies to add new entries:

     mclmcr.lib mclmcrrt.lib libmx.lib libmat.lib libMyAdd.lib 
  • Create a new MyAdd_test.cpp and put libMyAdd.dll , libMyAdd.h and libMyAdd.lib in the same folder. Add libMyAdd.h to the Header Files , libMyAdd.h and libMyAdd.lib to the Resource Files .

The code MyAdd_test.cpp as follows:

 #include "mclmcr.h" #include "matrix.h" #include "mclcppclass.h" #include "libMyAdd.h" int main() { double a = 6; double b = 9; double c; // initialize lib if( !libMyAddInitialize()) { std::cout << "Could not initialize libMyAdd!" << std::endl; return -1; } // allocate space mwArray mwA(1, 1, mxDOUBLE_CLASS); mwArray mwB(1, 1, mxDOUBLE_CLASS); mwArray mwC(1, 1, mxDOUBLE_CLASS); // set data mwA.SetData(&a, 1); mwB.SetData(&b, 1); // use function: MyAdd MyAdd(1, mwC, mwA, mwB); // get data c = mwC.Get(1, 1); printf("c is %f\n", c); // terminate the lib libMyAddTerminate(); // terminate MCR mclTerminateApplication(); return 0; } 

Finally, the result

 Compiling... MyAdd_test.cpp Linking... MyAdd_test.obj : error LNK2019: unresolved external symbol _mclTerminateApplication_proxy referenced in function _main MyAdd_test.obj : error LNK2019: unresolved external symbol _libMyAddTerminate referenced in function _main MyAdd_test.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) void __cdecl MyAdd(int,class mwArray &,class mwArray const &,class mwArray const &)" ( __imp_?MyAdd@ @ YAXHAAVmwArray@ @ ABV1@1 @Z) referenced in function _main MyAdd_test.obj : error LNK2019: unresolved external symbol _libMyAddInitialize referenced in function _main MyAdd_test.obj : error LNK2019: unresolved external symbol _mclGetMatrix referenced in function "public: __thiscall mwArray::mwArray(unsigned int,unsigned int,enum mxClassID,enum mxComplexity)" ( ??0mwArray@ @ QAE@IIW4mxClassID @@ W4mxComplexity@ @@Z) MyAdd_test.obj : error LNK2019: unresolved external symbol _mclcppGetLastError referenced in function "public: static void __cdecl mwException::raise_error(void)" ( ?raise_error@mwException @@SAXXZ) MyAdd_test.obj : error LNK2019: unresolved external symbol _mclcppCreateError referenced in function "public: __thiscall mwException::mwException(void)" ( ??0mwException@ @ QAE@XZ ) MyAdd_test.obj : error LNK2019: unresolved external symbol _ref_count_obj_addref referenced in function "public: __thiscall mwException::mwException(class mwException const &)" ( ??0mwException@ @ QAE@ABV0 @@Z) MyAdd_test.obj : error LNK2019: unresolved external symbol _ref_count_obj_release referenced in function "public: virtual __thiscall mwException::~mwException(void)" ( ??1mwException@ @ UAE@XZ ) MyAdd_test.obj : error LNK2019: unresolved external symbol _error_info_get_message referenced in function "public: virtual char const * __thiscall mwException::what(void)const " ( ?what@mwException @@UBEPBDXZ) MyAdd_test.obj : error LNK2019: unresolved external symbol _array_ref_getV_int referenced in function "public: class mwArray __cdecl mwArray::GetPromoted(unsigned int,...)" ( ?GetPromoted@mwArray @@ QAA?AV1@IZZ ) MyAdd_test.obj : error LNK2019: unresolved external symbol _array_ref_set_numeric_mxDouble referenced in function "public: void __thiscall mwArray::SetData(double *,unsigned int)" ( ?SetData@mwArray @@ QAEXPANI@Z ) MyAdd_test.obj : error LNK2019: unresolved external symbol _array_ref_get_numeric_mxDouble referenced in function "public: __thiscall mwArray::operator double(void)const " ( ??BmwArray@ @QBENXZ) C:\Users\WangYudong\Documents\Visual Studio 2008\Projects\MyAdd_C\Debug\MyAdd_C.exe : fatal error LNK1120: 13 unresolved externals 

Actually, the work above is my test for calling the user-defined MATLAB function from C ++. My next job is to convert the MATLAB program to C ++, which contains image processing functions like imread , edge , imread , etc. I tried MATLAB Coder but cannot convert MATLAB functions. So I try the method above. Is this an efficient way to convert these functions, or should I implement them using OpenCV?

+6
source share
1 answer

Before you begin, make sure that a supported compiler is installed. It will be Visual C ++ and possibly the Windows SDK if you are using the VS Express version on 64-bit Windows. Then you need to configure MATLAB by following these steps at least once:

 >> mex -setup >> mbuild -setup 

Now the following simple function is given:

Myadd.m

 function c = MyAdd(a,b) c = a + b; end 

We want to build a common C ++ library using the MATLAB mcc compiler:

 >> mcc -N -W cpplib:libMyAdd -T link:lib MyAdd.m -v 

This will create a couple of files, including a header file, a DLL, and an import library:

 libMyAdd.h libMyAdd.dll libMyAdd.lib 

Next, create a C ++ program to test the above library:

Myadd_test.cpp

 #include "libMyAdd.h" int main() { // initialize MCR and lib if (!mclInitializeApplication(NULL,0)) { std::cerr << "could not initialize the application" << std::endl; return -1; } if(!libMyAddInitialize()) { std::cerr << "Could not initialize the library" << std::endl; return -1; } try { // create input double a[] = {1.0, 2.0, 3.0, 4.0}; double b[] = {5.0, 6.0, 7.0, 8.0}; mwArray in1(2, 2, mxDOUBLE_CLASS, mxREAL); mwArray in2(2, 2, mxDOUBLE_CLASS, mxREAL); in1.SetData(a, 4); in2.SetData(b, 4); // call function mwArray out; MyAdd(1, out, in1, in2); // show result std::cout << "in1 + in2 = " << std::endl; std::cout << out << std::endl; double c[4]; out.GetData(c, 4); for(int i=0; i<4; i++) { std::cout << c[i] << " " << std::endl; } } catch (const mwException& e) { std::cerr << e.what() << std::endl; return -2; } catch (...) { std::cerr << "Unexpected error thrown" << std::endl; return -3; } // cleanup libMyAddTerminate(); mclTerminateApplication(); return 0; } 

We could compile this program directly from inside MATLAB using:

 >> mbuild MyAdd_test.cpp libMyAdd.lib -v >> !MyAdd_test 

We could also compile it ourselves using Visual Studio. We start by creating our own console application, and then set the project parameters as follows:

  • From the menu, select "Project> Properties" and apply the settings to "All configurations" (both for debugging and release purposes)
  • In the C / C ++ properties, set “Additional Include Directories” by adding to the directory the directory containing the generated header file libMyAdd.h , in addition to the directory containing the MATLAB header files:

     $matlabroot\extern\include 
  • Similarly, in the "Linker" section, install "Additional library directories." This will be the same directory as before containing libMyAdd.lib , and also in my case:

     $matlabroot\extern\lib\win32\microsoft 

    Then go to "Linker> Input" and add the following inside the "Additional Dependencies":

     libMyAdd.lib mclmcrrt.lib 
  • Finally, in the Debug> Environment section, you can expand the PATH environment variable to include the directory containing the generated libMyAdd.dll file. This way you can directly press F5 to compile running the program directly from inside VS. It will be something like this:

     PATH=%PATH%;C:\path\to\output\folder 

If you do this often, you can create a property sheet once, which can then be reused in other VC ++ projects. See this answer for an example.

+4
source

Source: https://habr.com/ru/post/947352/


All Articles