http://matlab.izmiran.ru/help/techdoc/matlab_external/ch04cre7.html

 

 

External Interfaces Previous page   Next Page

Passing Two or More Inputs or Outputs

The plhs[] and prhs[] parameters are vectors that contain pointers to each left-hand side (output) variable and each right-hand side (input) variable, respectively. Accordingly, plhs[0]contains a pointer to the first left-hand side argument, plhs[1] contains a pointer to the second left-hand side argument, and so on. Likewise, prhs[0] contains a pointer to the first right-hand side argument, prhs[1] points to the second, and so on.

This example, xtimesy, multiplies an input scalar by an input scalar or matrix and outputs a matrix. For example, using xtimesy with two scalars gives

  • x = 7;
    y = 7;
    z = xtimesy(x,y)
    
    z = 
         49
    

Using xtimesy with a scalar and a matrix gives

  • x = 9;
    y = ones(3);
    z = xtimesy(x,y)
    
    z = 
         9      9      9
         9      9      9
         9      9      9
    

This is the corresponding MEX-file C code.

  • /*
     * =============================================================
     * xtimesy.c - example found in API guide
     *
     * Multiplies an input scalar times an input matrix and outputs a
     * matrix. 
     *
     * This is a MEX-file for MATLAB.
     * Copyright (c) 1984-2000 The MathWorks, Inc.
     * =============================================================
     */
    
    /* $Revision: 1.10 $ */
    
    #include "mex.h"
    
    void xtimesy(double x, double *y, double *z, int m, int n)
    {
      int i,j,count = 0;
      
      for (i = 0; i < n; i++) {
        for (j = 0; j < m; j++) {
          *(z+count) = x * *(y+count);
          count++;
        }
      }
    }
    
    
    /* The gateway routine */
    void mexFunction(int nlhs, mxArray *plhs[],
                     int nrhs, const mxArray *prhs[])
    {
      double *y, *z;
      double x;
      int status,mrows,ncols;
      
      /*  Check for proper number of arguments. */
      /* NOTE: You do not need an else statement when using
         mexErrMsgTxt within an if statement. It will never
         get to the else statement if mexErrMsgTxt is executed.
         (mexErrMsgTxt breaks you out of the MEX-file.) 
      */
      if (nrhs != 2) 
        mexErrMsgTxt("Two inputs required.");
      if (nlhs != 1) 
        mexErrMsgTxt("One output required.");
      
      /* Check to make sure the first input argument is a scalar. */
      if (!mxIsDouble(prhs[0]) || mxIsComplex(prhs[0]) ||
          mxGetN(prhs[0])*mxGetM(prhs[0]) != 1) {
        mexErrMsgTxt("Input x must be a scalar.");
      }
      
      /* Get the scalar input x. */
      x = mxGetScalar(prhs[0]);
      
      /* Create a pointer to the input matrix y. */
      y = mxGetPr(prhs[1]);
      
      /* Get the dimensions of the matrix input y. */
      mrows = mxGetM(prhs[1]);
      ncols = mxGetN(prhs[1]);
      
      /* Set the output pointer to the output matrix. */
      plhs[0] = mxCreateDoubleMatrix(mrows,ncols, mxREAL);
      
      /* Create a C pointer to a copy of the output matrix. */
      z = mxGetPr(plhs[0]);
      
      /* Call the C subroutine. */
      xtimesy(x,y,z,mrows,ncols);
    }
    

As this example shows, creating MEX-file gateways that handle multiple inputs and outputs is straightforward. All you need to do is keep track of which indices of the vectors prhs andplhs correspond to the input and output arguments of your function. In the example above, the input variable x corresponds to prhs[0] and the input variable y to prhs[1].

Note that mxGetScalar returns the value of x rather than a pointer to x. This is just an alternative way of handling scalars. You could treat x as a 1-by-1 matrix and use mxGetPr to return a pointer to x.


 

Previous page   Passing Strings   Passing Structures and Cell Arrays  Next page

© 1994-2005 The MathWorks, Inc.


 

Posted by uniqueone
,

http://www.ninadthakoor.com/2012/03/03/matcv/


        //Transpose the opencv data to get row major data for matlab
        tmp=opencv.t();

opencv mat를 matlab mex 데이터로 변환할때는 .t()로 transpose시켜줘야 한다.



Using OpenCV functions in Matlab

I wrote Converter class few days back to simplify creating MEX files for OpenCV functions. Example of using the class follows in the next post.

Source for matcv.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#ifndef __MATCV__H__
#define __MATCV__H__
 
#include &quot;mex.h&quot;
#include &quot;matrix.h&quot;
#include &lt;cstring&gt;
#include &quot;opencvcv.h&quot;
#include &quot;opencvhighgui.h&quot;
#include &quot;boostbimap.hpp&quot;
 
class Converter{
public:
 Converter(mxArray* src, bool Interleve=true);
 Converter(cv::Mat&amp; src);
 
 operator cv::Mat();
 operator mxArray*();
 
private:
 enum{MATLAB_MXARRAY,OPENCV_MAT} _id;
 bool _interleve;
 
 cv::Mat opencv;
 mxArray* matlab;
 
 typedef boost::bimap&lt;mxClassID,unsigned char&gt; bmtype;
 bmtype _idmap;
 void _initidmap();
 
 void _matlab2opencv();
 void _opencv2matlab();
};
 
#endif //__MATCV__H__

Source for matcv.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#include &quot;matcv.h&quot;
 
Converter::Converter(mxArray* src,bool Interleve):matlab(src),_id(MATLAB_MXARRAY),_interleve(Interleve){
    _initidmap();
}
Converter::Converter(cv::Mat&amp; src):opencv(src),_id(OPENCV_MAT){
    _initidmap();
}
 
Converter::operator cv::Mat()
{
    if(_id==OPENCV_MAT)
        return(opencv);
    _matlab2opencv();
    return(opencv);
}
 
Converter::operator mxArray*()
{
    if(_id==MATLAB_MXARRAY)
        return(matlab);
    _opencv2matlab();
    return(matlab);
}
 
void Converter::_initidmap()
{
    _idmap.insert(bmtype::value_type(mxINT8_CLASS,CV_8S));
    _idmap.insert(bmtype::value_type(mxUINT8_CLASS,CV_8U));
    _idmap.insert(bmtype::value_type(mxINT16_CLASS,CV_16S));
    _idmap.insert(bmtype::value_type(mxUINT16_CLASS,CV_16U));
    _idmap.insert(bmtype::value_type(mxINT32_CLASS,CV_32S));
    _idmap.insert(bmtype::value_type(mxSINGLE_CLASS,CV_32F));
    _idmap.insert(bmtype::value_type(mxDOUBLE_CLASS,CV_64F));
}
 
void  Converter::_opencv2matlab()
{
    //Is the data type supported?
    bmtype::right_map::const_iterator itr=_idmap.right.find(opencv.depth());
     
    //if not then
    if(itr==_idmap.right.end())
    {
        mexErrMsgTxt(&quot;OpenCV2Matlab:Unsupported data type.&quot;);
    }
     
    //Find the matlab data type
    mxClassID type=itr-&gt;second;
     
    //We support max 3 dimensions
    mwSignedIndex dims[3];
    dims[0]=opencv.rows;
    dims[1]=opencv.cols;
    dims[2]=opencv.channels();
     
    //if number of channels is 1, its a 2D array
    if(dims[0]&gt;0 &amp;&amp; dims[1]&gt;0 &amp;&amp; dims[2]==1)
    {
        //Create the array to be returned
        matlab=mxCreateNumericArray(2,dims,type,mxREAL);
        //Create opencv header for the matlab data
        cv::Mat tmp=cv::Mat(dims[1],dims[0],CV_MAKETYPE(opencv.depth(),1),mxGetData(matlab),0);
        //Transpose the opencv data to get row major data for matlab
        tmp=opencv.t();
         
        const mwSize* size=mxGetDimensions(matlab);
        mxAssert((opencv.rows==size[0])&amp;(opencv.cols==size[1]),&quot;OpenCV2Matlab:Conversion mismatch&quot;);
    }
    else
    {
        //Create the array to be returned
        matlab=mxCreateNumericArray(3,dims,type,mxREAL);
         
        //Seperate the channels
        std::vector&lt;cv::Mat&gt; chans(dims[2]);
        //cv::split(opencv,&amp;chans[0]);
        cv::split(opencv,chans);
         
        //Create opencv header as a &quot;flat&quot; image for the matlab data
        cv::Mat tmp=cv::Mat(dims[1]*dims[2],dims[0],CV_MAKETYPE(opencv.depth(),1),mxGetData(matlab),0);
         
        for(int i=0;i&lt;dims[2];i++)
        {
            //transpose the opencv channels image to row major matlab data
            cv::Mat tmp2=chans[i].t();
            //Copy the data to the flat matlab data
            tmp2.copyTo(tmp.rowRange(i*dims[1],(i+1)*dims[1]));
        }
         
        const mwSize* size=mxGetDimensions(matlab);
        mxAssert((opencv.rows==size[0])&amp;(opencv.cols==size[1])&amp;(opencv.channels()==size[2]),&quot;OpenCV2Matlab:Conversion mismatch&quot;);
    }  
}
 
void  Converter::_matlab2opencv()
{
    //find the corresponding corresponding opencv data type
    bmtype::left_map::const_iterator itr=_idmap.left.find(mxGetClassID(matlab));
     
    //No corresponding type?
    if(itr==_idmap.left.end()| mxIsComplex(matlab) | mxIsSparse(matlab))
    {
        std::string msg=&quot;Matlab2OpenCV:Unsupported data type:&quot;+(itr==_idmap.left.end()?std::string(mxGetClassName(matlab)):&quot;&quot;)
        +(mxIsComplex(matlab)?&quot; Complex&quot;:&quot;&quot;)+(mxIsSparse(matlab)?&quot; Sparse&quot;:&quot;.&quot;);
        mexErrMsgTxt(msg.c_str());
    }
     
    unsigned char type=itr-&gt;second;
     
    //Get number of dimensions
    const mwSize dims=mxGetNumberOfDimensions(matlab);
     
    //Cannot handle more that 3 dimensions
    if(dims&gt;3)
    {
        std::ostringstream o;
        o&lt;&lt;&quot;Matlab2OpenCV:Supports upto 3 dimensions. You supplied &quot;&lt;&lt;dims&lt;&lt;&quot;.&quot;;
        mexErrMsgTxt(o.str().c_str());
    }
     
    //Get actual dimensions
    const mwSize* size=mxGetDimensions(matlab);
     
    //Check if 2 or 3 dimentions
    if(dims==2)
    {
        //Create header for row major matlab data
        const cv::Mat donotmodify=cv::Mat(size[1],size[0],CV_MAKETYPE(type,1),mxGetData(matlab),0);
         
        //Transpose the data so that it is column major for opencv.
        opencv=donotmodify.t();
        mxAssert((opencv.rows==size[0])&amp;(opencv.cols==size[1]),&quot;Matlab2OpenCV:Conversion mismatch&quot;);
    }
    else
    {
        //Create header for the &quot;flat&quot; matlab data
        const cv::Mat donotmodify=cv::Mat(size[1]*size[2],size[0],CV_MAKETYPE(type,1),mxGetData(matlab),0);
         
        //Transpose the flat data
        cv::Mat flat=donotmodify.t();
         
        //Create vector of channels to pass to opencv merge operataion
        std::vector&lt;cv::Mat&gt; chans(size[2]);
         
        for(int i=0;i&lt;size[2];i++)
        {
            chans[i]=flat.colRange(i*size[1],(i+1)*size[1]);
        }
        cv::merge(chans,opencv);
        mxAssert((opencv.rows==size[0])&amp;(opencv.cols==size[1])&amp;(opencv.channels()==size[2]),&quot;Matlab2OpenCV:Conversion mismatch&quot;);
    }
}


Posted by uniqueone
,

http://stackoverflow.com/questions/27514658/way-to-send-opencv-mat-to-matlab-workspace-without-copying-the-data



When I write MEX files which use OpenCV functions it's easy to pass the data from MATLAB to the MEX environment without copying the data. Is there a way to return the data to MATLAB in the same manner? (That is, without copying the data and without causing MATLAB to crash...)

A simple example:

#include "mex.h"
#include "/opencv2/core.hpp"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs,const mxArray *prhs[])
{

    Rows=mxGetM(prhs[0]);
    Cols=mxGetN(prhs[0]);
    Mat InMat(Cols,Rows,CV_64FC1,mxGetPr(prhs[0]));//Matlab passes data column-wise 
                                                   // no need to copy data - SUPER!

    InMat=InMat.t();//transpose so the matrix is identical to MATLAB's one

    //Make some openCV operations on InMat to get OutMat...


    //Way of preventing the following code??

    plhs[0]=mxCreateDoubleMatrix(OutMat.rows,OutMat.cols,mxREAL);
    double *pOut=mxGetPr(plhs[0]);

    for (int i(0);i<OutMat.rows;i++)
      for (int j(0);j<OutMat.cols;j++)
         pOut[i+j*OutMat.rows]=OutMat.at<double>(i,j);

}



-----------------------------------------

Usually I do the input and output just like that, attaching a pointer to deal with the input and looping over elements on output. But, I think the output can be done in a similar manner to the input, although not without a copy of some sort. The only way to avoid a copy is to create the output Mat with a pointer from a mxArray and operate on it inplace. That's not always possible, of course. But you can be graceful about how you copy the data out.

You can exploit the same trick of attaching a buffer to a cv::Mat that you use (me too!) to bring data in from MATLAB, but also to get it out. The twist on the trick to exporting the data is to use copyTojust right so that it will use the existing buffer, the one from the mxArray in plhs[i].

Starting with an input like this:

double *img = mxGetPr(prhs[0]);
cv::Mat src = cv::Mat(ncols, nrows, CV_64FC1, img).t(); // nrows <-> ncols, transpose

You perform some operation, like resizing:

cv::Mat dst;
cv::resize(src, dst, cv::Size(0, 0), 0.5, 0.5, cv::INTER_CUBIC);

To get dst into MATLAB: first transpose the output (for sake of reordering the data into col-major order) then create an output cv::Mat with the pointer from the plhs[0] mxArray, and finally call copyTo to fill out the wrapper Mat with the transposed data:

dst = dst.t(); // first!
cv::Mat outMatWrap(dst.rows, dst.cols, dst.type(), pOut); // dst.type() or CV_*
dst.copyTo(outMatWrap); // no realloc if dims and type match

It is very important to get the dimensions and data type exactly the same for the following call to copyTo to keep from reallocating outMatWrap.

Note that when outMatWrap is destroyed, the data buffer will not be deallocated because the reference count is 0 (Mat::release() does not deallocate .data).


Possible template (by no means bullet-proof!)

template <typename T>
void cvToMATLAB(cv::Mat mat, T *p)
{
    CV_Assert(mat.elemSize1() == sizeof(T));
    mat = mat.t();
    cv::Mat outMatWrap(mat.rows, mat.cols, mat.type(), p);
    mat.copyTo(outMatWrap);
}

This should be good for channels>1, as long as the size of the MATLAB array is in pixel order too (e.g. 3xMxN). Then use permute as needed.


Note about copyTo

The conditions under which copyTo will reallocate the destination buffer are if the dimensions or data type do not match:

opencv2\core\mat.hpp line 347 (version 2.4.10), with my comments:

inline void Mat::create(int _rows, int _cols, int _type)
{
    _type &= TYPE_MASK;
    if( dims <= 2 && rows == _rows && cols == _cols && type() == _type && data )
        return;    // HIT THIS TO USE EXISTING BUFFER!
    int sz[] = {_rows, _cols};
    create(2, sz, _type); // realloc!
}

So, just make sure you get the size and data type correct, and the data will end up in the mxArraybuffer instead of somewhere else. If you do it right, copyTo will use the buffer you specified, calling memcpy on each row.


Posted by uniqueone
,
https://www.stereolabs.com/blog/index.php/tag/matlab/

 

아래 설명에 나온것처럼 cmake로 mex파일을 생성할때는, visual studio sln파일을 만든 후, 그 프로젝트를 빌드한 후, INSTALL을 빌드해주면 mex파일이 생성된다.

 

 

 

  • Right click on the project named ‘mexZED’ and select ‘Build’
  • Right click on the project named ‘INSTALL’ and select ‘Build’
  • ---------------------------------------------------

     

    Introduction

    The purpose of this post is to explain how to use the ZED stereo camera and its SDK to capture depth maps with Matlab. We use the ability of Matlab to execute C++ code through an intermediate file called MEXA file.

    You will find the complete source code on Stereolabs’ Github page.

    If you simply want to use the ZED stereo camera with Matlab (without the ZED SDK) you can refer to this article.

    Prerequisites

    You must have Matlab installed on your system and of course, the ZED SDK needs to be installed too.

    Code

    When downloading the source code from GitHub, you will find two subfolders. The first one, ‘matlab’, contains a file named ‘ZED_Camera.m’, a standard Matlab file wich will call the ZED functions. The second subfolder, ‘src’, contains the files to build the application.
    In the ‘mex’ subfolder, there is a file named ‘mexZED.cpp’ which contains the ZED SDK functions and interoperability with the Matlab format. This file is referred to as a MEX file. It re-implements the majority of the ZED SDK functions. This file is provided as a basic container and can be complemented with your own functions. Since Matlab does not handle image representation the same way the ZED SDK does, we need additional formatting functions.In the file ‘ZED_Camera.m’ the ZED functions are reachable through mexZED(‘..’). Check the ‘mexZED.cpp’ to see the list of functions available.

    Build procedure

    You now want to compile the mexZED.cpp file in a MEXA file format which can be used by Matlab. Usually, MEX files are compiled directly by Matlab but since we need to link several libraries (ZED, OpenCV) it is better to use CMake.
    On Linux

    Open a terminal in zed-Matlab directory and execute the following command:

    export MATLAB_ROOT=/usr/local/MATLAB/R2012b
    mkdir build
    cd build
    cmake ../src
    make
    make install
    On Windows

    You need to set the environment variable ‘MATLAB_ROOT’, to do this you can use an editor such as ‘Rapid Environment Editor’ or use the following procedure:

     

    • Click the Start button, right-click on ‘Computer’ and select ‘Properties’.
    • Click the ‘Advanced System Settings’ link in the left column.
    • In the System Properties window, click on the ‘Advanced’ tab, then click the ‘Environment Variables…’ button in the bottom of the window.
    • In the upper part of the window, add your definition to ‘User variables for..’
    • Click ‘New…’
    • Set ‘Variable name’ as MATLAB_ROOT
    • Set ‘Variable value’ to your own matlab root directory e.g. ‘C:\Program Files\MATLAB\R2014b’
    • Restart your computer.

     

     

     

    Then a common build procedure is used:

    • Open cmake-gui.
    • In “Where is the source code”, enter the path of the sources (e.g. ‘C:\Users\Peter\Documents\zed-matlab\src’)
    • In “Where to build the binaries”, enter the build directory (e.g. ‘C:\Users\Peter\Documents\zed-matlab\build’), and click the “Configure” button.
    • A dialog window asks you if CMAKE can create the folder “build” itself. Say yes.
    • Another dialog window will ask you the generator of your project. Choose Visual Studio. For example, we choose “Visual Studio 12 2013”. Click the “Finish” button.
    • CMAKE may take few seconds to configure the project. Then, some red lines should be displayed in the cmake-gui window.
    • Make sure that the message ‘MATLAB Found, MATLAB MEX will be compiled.’ is print, if not the variable environment MATLAB_ROOT can not be found, and you can not compile the project.
    • Click the “Generate” button.
    • CMAKE has just generated your project in the build folder. Now, you can close the cmake-gui window and go to the build folder.
    • Visual Studio files has been generated and a Visual Studio project file named “MEX.sln” too. Open it with Visual Studio.
    • Right click on the project named ‘mexZED’ and select ‘Build’
    • Right click on the project named ‘INSTALL’ and select ‘Build’

     

    Run the sample

    You can now find the generated MEXA file in the matlab directory (e.g. ‘\zed-matlab\matlab’), you can launch Matlab and run the ZED_Camera.m file.

    matlab

    Read More

    Posted by uniqueone
    ,

    아래와 같이 따라해보니 간단한 mex파일이 생성되었다.

    http://stackoverflow.com/questions/26220193/building-a-matlab-mex-file-in-visual-studio-gives-lnk2019-unresolved-external-s

    You need to create a Visual Studio project that produces DLLs (as opposed to console or GUI applications). MEX-files are basically shared libraries with a custom extension (*.mexw32 or *.mexw64 on Windows)

    The error message indicates that the linker cannot find the entry-point function main() for an executable, which does not exist for dynamic libraries.

    For what it's worth, you can run mex -v ... in MATLAB, that way it shows you the exact commands used to invoke the compiler and linker.


    EDIT:

    Step-by-step instructions:

    • create a new empty VS project to build DLLs (Visual C++ > Win32 > Win32 console application , (이름입력후 ok를 누른 후) then set the (application) type to DLL in the wizard)

    • Since we're working with MATLAB x64, we need to adjust project configuration to generate 64-bit binaries. From Build menu, select Configuration Manager. From the drop-down menu choose <New> to create a new platform configs, select x64 and accept.

    • follow the previous instructions you mentioned

    • add the C/C++ source code for the MEX-file

      #include "mex.h"
      void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
      {
          plhs[0] = mxCreateString("hello world");
      }
      
    • switch platform to "x64" in "Release" mode, and build the project. Now you should have a somefile.mexw64 MEX-file which you can call in MATLAB as a regular function.

    --------------------------------------------

    위의 instructions 은 아래이다. (http://stackoverflow.com/questions/16716821/how-to-build-mex-file-directly-in-visual-studio/16718578#16718578)

    After some experimenting with guidance from this page mentioned in the question, it seems like starting with an empty C++ project the following settings in the project's Property Pages are necessary and sufficient to build a working .mexw64 from Visual Studio 2010:

    Configuration properties -> General:
        Set Target Extension to .mexw64
        Set Configuration Type to Dynamic Library (.dll)
    
    Configureation poperties -> VC++ Directories:
        Add $(MATLAB_ROOT)\extern\include; to Include Directories
    
    Configuration properties -> Linker -> General:
        Add $(MATLAB_ROOT)\extern\lib\win64\microsoft; to Additional Library Directories
    
    Configuration properties -> Linker -> Input:
        Add libmx.lib;libmex.lib;libmat.lib; to Additional Dependencies
    
    Configuration properties -> Linker -> Command Line:
        Add /export:mexFunction to Additional Options
    

    $(MATLAB_ROOT) is the path to Matlab's root folder, eg. C:\Program Files\MATLAB\R2013a.

    So far this has only been tried from a solution created from scratch and built for Matlab 2013a 64-bit. I assume that to build for 32-bit one only needs to change both occurrences of 64 to 32. I will update the post when I have confirmed that this works for an existing solution.

    EDIT: As expected this works for projects added to existing solutions. Remember to set the new project to be dependent on the project that creates the library.

    Edit 2: Following this question I can confirm that the above steps work in Visual Studio 2012 and 2013 too.

    Posted by uniqueone
    ,

     

    Error using mex
       Creating library example_mex_function.lib and object example_mex_function.exp
    example_mex_function.obj : error LNK2019: unresolved external symbol utIsInterruptPending referenced in function "void __cdecl dlib::check_for_matlab_ctrl_c(void)" (?check_for_matlab_ctrl_c@dlib@@YAXXZ)
    example_mex_function.mexw64 : fatal error LNK1120: 1 unresolved externals

     

    이런 에러가 떠서 검색하여 아래와 같이 하니 됐다.

     

    mex -O "example_mex_function.cpp" -I"D:\Research\dlib\dlib-19.0" "C:\Program Files\MATLAB\R2016a\extern\lib\win64\microsoft\libut.lib"

    Posted by uniqueone
    ,
    http://darkblitz.tistory.com/category/%EC%82%BD%EC%A7%88%EC%9D%BC%EA%B8%B0?page=2

     

     

    Energy minimization 부분을 살펴보다 관련 소스를 얻어 컴파일하려고 하니 아래와 같은 오류가 발생하였다.


     error LNK2019: unresolved external symbol utIsInterruptPending referenced in function...


    utIsInterruptPending가 extern으로 선언되어 있으나 링크되지 않아서 생기는 문제였다.


    utIsInterruptPending가 어디에 쓰는 함수인고 하니, Ctrl+C가 입력되었을 때, 이를 처리하는 함수라고 한다.


    utIsInterruptPending는 undocumented MATLAB API로 libut.dll에 구현되어 있으며, libut.lib를 mex 컴파일시에 링크해주면 되겠다. libut.lib는 기본적으로 mex에서 링크하지 않고 있으므로 -l옵션을 이용하여 추가해 주어야한다. 다음과 같이 하면 되겠다.


    mex blahblah.cpp -lut


    출처: http://www.caam.rice.edu/~wy1/links/mex_ctrl_c_trick/

     

    Posted by uniqueone
    ,
    https://victorfang.wordpress.com/2011/09/06/

     

    아래의 코드에서

    원래는 cc[i*n + j] = aa[i*n + j] + bb[i*n + j];가 comment돼 있으나, 이걸 풀고
    //C[i*n + j] = A[i*n + j] + B[i*n + j]; 이것을 comment시켜야 mex가 된다.

     

    To access the variables, you need to associate a pointer to the data in the mxArray. Once you do this, accessing the variables is very simple.


    a = mxGetPr(a_in_m);
    b = mxGetPr(b_in_m);
    c = mxGetPr(c_out_m);
    d = mxGetPr(d_out_m);

    Now it is possible to access the arrays with standard C or C++ [] notation. There are three important things to remember though:

    • You use 0-based indexing as always in C
    • You still use column-first indexing like in Matlab, though
    • To access the arrays, you use linear indexing (you can’t use [x][y], you have to use [y+x*dimy]

    With those three things in mind, go crazy. You can use standard C libraries (as long as you include them). You can use for loops as much as your heart desires, and your code will be much, much faster than its Matlab equivalent.

     

     

    Note that if we access using C[x] , we will get this error. In other words, we need to define another pointer to access the input memory space using: double *cc = mxGetPr(C);

     

    >> mex mextest.cpp
    mextest.cpp
    mextest.cpp(36) : error C2036: ‘mxArray *’ : unknown size
    mextest.cpp(36) : error C2036: ‘const mxArray *’ : unknown size
    mextest.cpp(36) : error C2036: ‘const mxArray *’ : unknown size
    mextest.cpp(36) : error C2676: binary ‘+’ : ‘const mxArray’ does not define this operator or a conversion to a type acceptable to the predefined operator

    C:\PROGRA~2\MATLAB\R2010B\BIN\MEX.PL: Error: Compile of ‘mextest.cpp’ failed.

    ??? Error using ==> mex at 208
    Unable to complete successfully.

     

     

     

    My working code:

    #include “mex.h”

    void mexFunction(int nlhs, mxArray *plhs[],
    int nrhs, const mxArray *prhs[])
    {
    /* more C/C++ code … */
    /* Check for proper number of arguments */
    if (nrhs != 2) {
    mexErrMsgTxt(“Two input arguments required.”);
    } else if (nlhs > 1) {
    mexErrMsgTxt(“Too many output arguments.”);
    }

    const mxArray *A = prhs[0];
    const mxArray *B = prhs[1];

    /* Check the dimensions of Y.  Y can be 4 X 1 or 1 X 4. */
    int m = mxGetM(A);
    int n = mxGetN(A);

    if (!mxIsDouble(A) || mxIsComplex(A) ) {
    mexErrMsgTxt(“YPRIME requires that Y be a 4 x 1 vector.”);
    }

    /* Create a matrix for the return argument */
    mxArray *C;
    C = plhs[0] = mxCreateDoubleMatrix(m, n, mxREAL);

    double *cc = mxGetPr(C);
    double *aa = mxGetPr(A);
    double *bb = mxGetPr(B);

    for(int i=0; i<m; i++){
    for(int j=0; j<n; j++){
    //cc[i*n + j] = aa[i*n + j] + bb[i*n + j];
    C[i*n + j] = A[i*n + j] + B[i*n + j];
    }
    }

    }

    Posted by uniqueone
    ,
    http://stackoverflow.com/questions/5622894/how-do-i-link-a-64-bit-matlab-mex-file-to-opencv-libraries

     

    mexFunction내에서 opencv가 라이브러리로 있을 때, mex 어떻게 시키는지 참고할수 있었음.

     

     

    Normally in MATLAB I can compile a mex file which uses OpenCV functions using:

    mex -O "mxFunc.cpp" -I"C:\OpenCV2.1\include/opencv" -L"C:\OpenCV2.1\lib" -lcv210 -lcvaux210 -lcxcore210 -lhighgui210

    However, having switched to a 64-bit version of MATLAB, I now get unresolved symbols, e.g.

    mxFunc.obj : error LNK2019: unresolved external symbol cvReleaseImage referenced in function mexFunction

    How can I fix this?

    System: Windows 7 64-bit; MSVC 2005; MATLAB R2010b 64-bit; OpenCV 2.1.0.

     

    -----------------------------------------------------------------------------------

    Generally: You need to recompile the used libraries in 64-bit.

    As far as I know, it's not enough. If you use STL (and the OpenCV uses a lot) you need to use the same CRT version what the Matlab uses. So you need to use the same version of MSVC what the Mathworks guys...

    You can check the dependency of the libmex.dll to figure out which CRT is needed. After it you need to install the proper Visual C++ (normally the free version is enough).

    -----------------------------------

    Using 64-bit libraries worked. I had to configure a new 64-bit MSVC solution using CMAKE, naming the "Generator" as "Visual Studio 8 2005 Win64". I don't know whether the compiler that I used was the same as that used to generate libmex.dll, but it worked anyway. – user664303 Apr 12 '11 at 10:23
        
    @user664303: The 32-bit version of the 2010a/20010b uses VS 2005. I suppose they use the same version for the 64-bit. You were lucky. :) – tr3w Apr 15 '11 at 16:54

    Posted by uniqueone
    ,

    http://www.mathworks.com/matlabcentral/answers/169911-cpp-file-in-matlab

     

    Hi,

    you will need to tell mex where to find the include files, and probably also the library files. Your call should look something like

    mex -I"C:\Program Files\opencv\include" Loadimage.cpp -l"C:\Program Files\opencv\lib" -Lopencv.lib
    

    Take a look at the doc for mex and there at the flags "-I", "-L", "-l".

    Titus

    Posted by uniqueone
    ,