How to use the C++ Interface to Matlab Rahul Nair May 6, 2009 1 Before we start (Things worth knowing) Matlab always employs Copy on demand. In assignments of the for a = b as well as when arguments are passed to functions.Only references or pointers are passed. Only if subsequently the assigned array is changed, matlab will copy the data. This also applies to mex functions. Matlab does not copy the data but only provides pointers to the memory, where the data is managed. Note that copy on demand is not enforced while using mexFunctions. So it is (as of version 2008) quite possible to manipulate data passed as function parameters in place. (Though most probably not really recommended, as this is not default matlab behaviour) To avoid copying large amount of data while using the C++ Interface, but still having the comfort of using Classes and Objects, VIGRA provides View classes. These are basically enhanced pointers to external memory providing methods that work on it. It would be advisible to have a look at the functions already written as much of the following will most probably be easier to understand. 2 The Gateway function The mexFunction(...) gateway is replaced by the vigraMexFunction(...) gateway. The mexFunction still exists - but is in matlab.hxx. It only creates the InputArray and OutputArray objects and subsequently calls vigraMexFunction(...) Note: if for some reason you do not want to use a custom mexFunction it is possible to override default behavior by #define CUSTOM MEX FUNCTION before #include matlab.hxx The two main classes needed for using the interface are vigra::matlab::InputArray and vigra::matlab::OutputArray. These two classes take the plhs prhs and nlhs nrhs parameters of the classical mexFunction and provide methods that simplify access of data. The job of the vigraMexFunction is to call the right template-instance of the vigraMain<>(..) function. Typechecking of the inputs etc should be done here. Note: vigra contains typedefs of kind UInt8 ... UInt64, Int8 ... Int64 Listing 1: The first parameter of the Function can be of type double or of type UInt8 1 2 3 4 5 6 7 8 void vigraMexFunction ( v i g r a : : matlab : : OutputArray outputs , v i g r a : : matlab : : I n p u t A r r a y i n p u t s ) { switch ( i n p u t s . typeOf ( 0 ) ) // s w i t c h on t h e t y p e o f t h e f i r s t p a r a m e t e r // c a l l s m x C l a s s I D t o g e t t h e a number c o r r e s p o n d i n g t o t h e t y p e { c a s e mxUINT8 CLASS : 1 9 10 11 12 13 14 15 v i g r a M a i n <U I n t 8 >( o u t p u t s , i n p u t s ) ; break ; c a s e mxDOUBLE CLASS : v i g r a M a i n <d o u b l e >( o u t p u t s , i n p u t s ) ; break ; default : mexErrMsgTxt ( ” Type o f i n p u t a t p o s i t i o n 0 n o t s u p p o r t e d ” ) ; } } Listing 2: Using Macros - This only works if vigraMain takes only one template parameter. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 void vigraMexFunction ( v i g r a : : matlab : : OutputArray outputs , v i g r a : : matlab : : I n p u t A r r a y i n p u t s ) { s w i t c h ( i n p u t s . t y p e O f ( ” someOption ” ) ) // s w i t c h on t h e t y p e o f t h e f i e l d ” someOption ” o f t h e o p t i o n s // s t r u c t . // c a l l s m x C l a s s I D t o g e t t h e a number c o r r e s p o n d i n g t o t h e t y p e { ALLOW UINT 16 64 // s w i t c h c a s e s f o r i n t 1 6 t o i n t 6 4 ALLOW INT 8 32 // s w i t c h c a s e s f o r i n t 8 t o i n t 3 2 ALLOW FD // a l l o w f l o a t and d o u b l e default : mexErrMsgTxt ( ” Type o f i n p u t a t p o s i t i o n 0 n o t s u p p o r t e d ” ) ; } } 3 The vigraMain function The vigraMain(...) function contains the C++ code that actually has to be run. First the View objects should look at the right data. Also space should be allocated for the output arrays. Listing 3: Examples 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 1. /∗Make a View o f Type T ( t h e t e m p l a t e t y p e o f v i g r a M a i n ) and l e t i t l o o k a t t h e f i r s t p a r a m e t e r s u p p l i e d . v r e q u i r e d ( ) i n d i c a t e s t h a t an mexErrMsgTxt ( ) i s t h r o w n i f no ar g u m e n t i s s u p p l i e d a t p o s i t i o n 0 ( o r an empty a r r a y ) ∗/ B a s i c I m a g e V i e w<T> in = i n p u t s . g e t I m a g e<T>(0 , v r e q u i r e d ( ) ) ; 2. /∗ Second Argument i s S c a l a r and c o p i e d i n t o ” s c a l e ” v d e f a u l t ( 1 . 0 ) i n d i c a t e s t h a t i f no ar g u m e n t i s s u p p l i e d t h e d e f a u l t v a l u e 1 . 0 i s u s e d . t h e l a s t two a r g u m e n t s a r e t h e r a n g e c o n s t r a i n t s on s c a l e a mexErrMsgTxt i s t h r o w n i f t h e v a l u e i s o u t o f bounds ∗/ double s c a l e = i n p u t s . g e t S c a l a r M i n M a x<d o u b l e >(1 , v d e f a u l t ( 1 . 0 ) , 0 . 0 , ” i n f ” ) ; 3. // C r e a t e an Image o f t y p e d o u b l e a t o u t p u t p o s i t i o n 0 w i t h t h e s i z e o f i n B a s i c I m a g e V i e w<d o u b l e> o u t = o u t p u t s . c r e a t e I m a g e <d o u b l e >(0 , v r e q u i r e d ( ) , i n . w i d t h ( ) , i n . h e i g h t ( ) ) ; 4. /∗Same t h i n g a s 2 . w i t h o u t c o n s t r a i n t s . v o p t i o n a l ( ) i n d i c a t e s t h a t t h i s v a r i a b l e does not have a d e f a u l t v a l u e . v o p t i o n a l ( bool check ) s e t s check to t r u e i f the v a r i a b l e h a s b e e n s e t , f a l s e o t h e r w i s e . ∗/ bool hasBackground ; T backgroundValue = i n p u t s . g e t S c a l a r <T>(” b a c k g r o u n d V a l u e ” , v o p t i o n a l ( h a s B a c k g r o u n d ) ) ; 5. /∗ c r e a t e s a s c a l a r a t t h e s e c o n o u t p u t i f s e c o n d o u t p u t h a s b e e n a s k e d f o r ( v o p t i o n a l ( ) ) and c o p i e s m a x r e g i o n l a b e l i n t o i t ∗/ o u t p u t s . c r e a t e S c a l a r <i n t > ( 1 , v o p t i o n a l ( ) , m a x r e g i o n l a b e l ) ; After space is allocated and the Views point to the right memory - the actual code can be executed. 2 4 matlab::InputArray and matlab::OutputArray These are wrapper classes for plhs nlhs, prhs nrhs respectively. InputArray checks whether the last mxArray* in prhs is a matlab struct array - If yes it is an options struct and loaded. What followes is a listing of public methods and attributes Place posOrName denotes an object of type std::string or an int. If it is std::string the options struct is searched for a field with name posOrNum. if it is an then the argument at the given position is used. ReqType is one of the objects described in the next section. Note: If you are not using matlab::InputArray or matlab::OutputArray, still you may use the non-member get and create functions which take a mxArray* as first parameter. Note that these functions do not check for constraints or whether the mxArray* is pointing to any memory. Look into matlab.hxx for further details. Listing 4: matlab::InputArray 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 matlab : : C o n s t S t r u c t A r r a y o p t i o n s /∗The o p t i o n s S t r u c t . See D o c u m e n t a t i o n o f C o n s t S t r u c t A r r a y f o r more i n f o r m a t i o n . ∗/ mxArray ∗ & o p e r a t o r [ ] ( P l a c e posOrName ) /∗ A c c e s s r e f e r e n c e t o t h e mxArray ∗ a t c e r t a i n p l a c e . ∗/ size type size () /∗ r e t u r n s n r h s ∗/ b o o l i s V a l i d ( P l a c e posOrName ) /∗ r e t u r n s t r u e i f a Argument was s u p p l i e d a t p l a c e posOrNum . ∗/ b o o l i s E m p t y ( P l a c e posOrName ) /∗ r e t u r n t r u e i f A r r a y a t p l a c e posOrNum i s empty . ∗/ m x C l a s s I D t y p e O f ( p l a c e posOrName ) /∗ r e t u r n t y p e o f mxArray ∗ a t p l a c e posOrNum ; ∗/ t e m p l a t e <c l a s s P l a c e , c l a s s ReqType> i n t getEnum ( P l a c e posOrName , ReqType r e q , s t d : : map<s t d : : s t r i n g , i n t > c o n s t & c o n v e r t e r ) /∗ g e t S t r i n g and c o n v e r t i n t o E n u m e r a t i o n t y p e See Note a f t e r t h e l i s t i n g f o r u s a g e ∗/ t e m p l a t e <c l a s s T , c l a s s p l a c e , c l a s s ReqType> T g e t S t r i n g ( p l a c e posOrName , ReqType r e q ) /∗ g e t S t r i n g a t p l a c e posOrName . ∗/ t e m p l a t e <c l a s s T , c l a s s p l a c e , c l a s s ReqType> T g e t S c a l a r ( p l a c e posOrName , ReqType r e q ) /∗ g e t S c a l a r v a l u e a t p l a c e posOrName . ∗/ t e m p l a t e<c l a s s T , c l a s s p l a c e , c l a s s r e q C l a s s , c l a s s m i n C l a s s , c l a s s m a x C l as s> T g e t S c a l a r M i n M a x ( p l a c e posOrName , r e q C l a s s r e q , m i n C l a s s min , m a x C l a s s max ) /∗ g e t S c a l a r v a l u e c o n s t r a i n e d by r a n g e d e f i n e d by m i n and max m i n and max can a l s o be ” i n f ” ∗/ t e m p l a t e <c l a s s T , c l a s s p l a c e , c l a s s r e q C l a s s , c l a s s i t e r a t o r T y p e > T g e t S c a l a r V a l s ( p l a c e posOrName , r e q C l a s s r e q , i t e r a t o r T y p e begin , i t e r a t o r T y p e end ) /∗ g e t S c a l a r v a l u e c o n s t r a i n e d by t h e v a l u e s i n t h e i t e r a t o r r a n g e g i v e n by b e g i n and e n d ∗/ t e m p l a t e <c l a s s T , c l a s s p l a c e , c l a s s r e q C l a s s , c l a s s i t e r a t o r T y p e > T g e t S c a l a r V a l s 2 D 3 D ( p l a c e posOrName , r e q C l a s s r e q , i t e r a t o r T y p e b e g i n 2 D , i t e r a t o r T y p e end2D , i t e r a t o r T y p e b e g i n 3 D , i t e r a t o r T y p e end3D , i n t dimVar ) /∗ g e t S c a l a r v a l u e c o n s t r a i n e d by r a n g e b e g i n 2 D , end2D i n c a s dimVar i s 2 e l s e c o n s t r a i n e d by r a n g e b e g i n 3 D , end3D ∗/ t e m p l a t e <c l a s s p l a c e , c l a s s r e q C l a s s > b o o l g e t B o o l ( p l a c e posOrName , r e q C l a s s r e q ) /∗ g e t l o g i c a l v a l u e . ∗/ t e m p l a t e <u n s i g n e d i n t N, c l a s s T , c l a s s p l a c e , c l a s s r e q C l a s s > 3 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 M u l t i A r r a y V i e w <N, T> g e t M u l t i A r r a y ( p l a c e posOrName , r e q C l a s s r e q ) /∗ g e t M u l t i A r r a y V i e w w i t h dim N and Type T∗/ template < c l a s s T, c l a s s place , c l a s s r e q C l a ss > B a s i c I m a g e V i e w<T> g e t I m a g e ( p l a c e posOrName , r e q C l a s s r e q ) /∗ g e t B a s i c I m a g e V i e w w i t h Type T∗/ t e m p l a t e<c l a s s T , u n s i g n e d i n t s z e , c l a s s p l a c e , c l a s s r e q C l a s s > T i n y V e c t o r V i e w< T , s z e > g e t T i n y V e c t o r ( p l a c e posOrName , r e q C l a s s r e q ) /∗ g e t T i n y V e c t o r V i e w o f Type T and s i z e s z e ∗/ t e m p l a t e< u n s i g n e d i n t s z e , c l a s s p l a c e , c l a s s r e q C l a s s > T i n y V e c t o r V i e w<M u l t i A r r a y I n d e x , s z e > g e t S h a p e ( p l a c e posOrName , r e q C l a s s r e q ) /∗ g e t M u t l i a r r a y S h a p e s i z e s z e ∗/ t e m p l a t e< c l a s s p l a c e , c l a s s r e q C l a s s > i n t g e t D i m O f I n p u t ( p l a c e posOrName , r e q C l a s s r e q ) /∗ g e t D i m e n s i o n o f I n p u t a t p l a c e posOrName ∗/ t e m p l a t e<c l a s s p l a c e , c l a s s r e q C l a s s > C o n s t C e l l A r r a y g e t C e l l A r r a y ( i n t pos , r e q C l a s s r e q ) /∗ g e t a O b j e c t o f t y p e C o n s t C e l l A r r a y NOTE : C e l l A r r a y may n o t be i n t h e s t r u c t ! ! ! ∗/ 4.1 1 2 Using the getEnum method VIGRA CREATE ENUM AND STD MAP4 ( MapName , C o r n e r , F o e r s t n e r , Rohr , B e a u d e t ) ; int method = i n p u t s . getEnum ( 2 , v d e f a u l t ( C o r n e r ) , MapName ) ; The first command is a macro. const int variables with names. Corner, Foerstner, Rohr and Beaudet. Also it creates a std::map MapName that maps the corresponding strings to the constants the method variable is then initialized with the getEnum method. Listing 5: matlab::OutputArray 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 mxArray ∗ & o p e r a t o r [ ] ( i n t p o s ) A c c e s s r e f e r e n c e t o t h e mxArray ∗ a t c e r t a i n p l a c e . size type size () returns nlhs bool i s V a l i d ( i n t pos ) r e t u r n s t r u e i f a Output was r e q u i r e d a t p o s i t i o n p o s . bool isEmpty ( i n t pos ) r e t u r n t r u e i f A r r a y a t p l a c e posOrNum i s empty . t e m p l a t e <u n s i g n e d i n t DIM , c l a s s T , c l a s s ReqType> M u l t i A r r a y V i e w <DIM , T> c r e a t e M u l t i A r r a y ( i n t pos , ReqType r e q , c o n s t T i n y V e c t o r <i n t , DIM> & s h a p e ) /∗ c r e a t e M u l t i A r r a y V i e w o f d i m e n s i o n Dim and t y p e T and a l l o c a t e enough s p a c e f o r s h a p e ∗/ t e m p l a t e <c l a s s T , c l a s s ReqType> B a s i c I m a g e V i e w<T> c r e a t e I m a g e ( i n t pos , ReqType r e q , mwSize w i d t h , mwSize h e i g h t ) t e m p l a t e <c l a s s T , c l a s s ReqType> B a s i c I m a g e V i e w<T> c r e a t e I m a g e ( i n t pos , ReqType r e q , typename M u l t i A r r a y S h a p e <2>:: t y p e c o n s t & s h a p e ) t e m p l a t e <c l a s s T , c l a s s ReqType> T∗ c r e a t e S c a l a r ( i n t pos , ReqType r e q ) /∗ a l l o c a t e memory f o r a s c a l a r and r e t u r n p o i n t e r t o i t . ∗/ t e m p l a t e <c l a s s T , c l a s s ReqType> v o i d c r e a t e S c a l a r ( i n t pos , ReqType r e q , T v a l ) /∗ a l l o c a t e memory f o r a s c a l a r and c o p y v a l i n t o i t . ∗/ t e m p l a t e <c l a s s ReqType> C o n s t C e l l A r r a y c r e a t e C e l l A r r a y ( i n t pos , ReqType r e q , mwSize s z e ) 4 5 The Required/Optional/Default objects The createType and getType functions always take an object of type Required, DefaultImpl<T>, DefaultImplVoid or bool as second argument Use the factory methods v_required(), v_default() and v_optional to create these objects: Listing 6: Behavior of the get/set functions with the factory objects 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 v required ( void ) /∗ g e n e r a t e s an e r r o r m e s s a g e i f t h e ar g u m e n t was n o t s u p p l i e d . ∗/ v optional () /∗ d o e s n o t h i n g . I f a rg u m e n t was n o t s u p p l i e d d e f a u l t c o n s t r u c t o r i s c a l l e d . ∗/ v o p t i o n a l ( bool f l a g ) /∗ same a s a b o v e . Only t h a t f l a g i s s e t i f a r gu m e n t was s u p p l i e d . f l a g i s f a l s e o t h e r w i s e . ∗/ /∗ A d d i t i o n a l l y when i n u s e w i t h t h e g e t method : ∗/ v default ( defaultVal ) /∗ r e t u r n s d e f a u l t V a l i f no ar g u m e n t s u p p l i e d . ∗/ v d e f a u l t ( defaultVal2D , defaultVal3D , dimSwitch ) /∗ i f d i m S w i t c h == 2 u s e d e f a u l t V a l 2 D e l s e u s e d e f a u l t V a l 3 D ∗/ Note: If you need to know whether an Object was set even if you used v_default(defaultval) Explicitly create the DefaultImpl<T> object (Only if using the first method): Listing 7: Finding out whether a default object was set 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 // c r e a t e a d e f a u l t M u l t i A r r a y M u l t i A r r a y <3, T> i n ( SomeShape ) ; // C r e a t e d e f a u l t I m p l o b j e c t D e f a u l t I m p l <typename M u l t i A r r a y V i e w <3,T> > d e f a u l t M u l t i A r r a y V i e w ( M u l t i A r r a y V i e w <3,T>( i n ) ) ; M u l t i A r r a y V i e w <3,T> Arg = i n p u t s . g e t M u l t i A r r a y <3,T>(0 , v d e f a u l t ( d e f a u l t M u l t i A r r a y V i e w ) ) ; // f i r s t way o f c h e c k i n g w h e t h e r Argument was s u p p l i e d : i f ( d e f a u l t M u l t i A r r a y V i e w . g a r b a g e == t r u e ) s t d : : c o u t << ” i t h a s b e e n s e t ” ; /∗ s e c o n d way o f c h e c k i n g w h e t h e r Argument was s u p p l i e d − o n l y w o r k s w i t h t h e View c l a s s e s , n o t w i t h s c a l a r s : ∗/ i f ( i n . d a t a ( ) == Arg . d a t a ( ) ) s t d : : c o u t << ” i t h a s n o t b e e n s e t ” ; 6 Build and Test scripts Use buildVigraExtensions and testVigraExtensions to build all mex files and to test the matlab.hxx interface. Note: The test script calls buildVigraExtensions to create the test mex files located in the test subdirectory 7 other classes The ConstStructArray object is used to store the options. It should not be necessary to manipulate the ConstStructArray directly. Listing 8: ConstStructArray (Options) ConstStructArray(mxArray* matPointer) /*Constructor.*/ operator[ 1 2 /∗ a c c e s s mxArray ∗ w h i c h i s f i e l d N a m e . ∗/ stored in the StructArray with 5 3 4 5 6 isValid () /∗ i s t r u e i f C o n s t S t r u c t A r r a y p o i n t s t o a v a l i d m a t P o i n t e r ∗/ i s V a l i d ( std : : s t r i n g ) /∗ t r u e i f f i e l d w i t h name s p e c i f i e d i n s t r i n g e x i s t s ∗/ This is just some experimental code but quite handy if you have make and handle sparse arrays. Basically just a wrapper class to a stl::map; Listing 9: Sparse array 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 t e m p l a t e<c l a s s T> class SparseArray private : s t d : : map<T i n y V e c t o r <i n t ,2 > , T , ShapeCmp> d a t a ; i n t width , l e n g t h ; public : SparseArray ( i n t i = 1 , i n t j = 1) // c a l l s a s s i g n ; void a s s i g n ( i n t i = 1 , i n t j = 1) /∗ s e t i n t r i n s i c s i z e o f t h e S p a r s e A r r a y − o n l y n e e d e d when u s i n g map To MxArray . ∗/ T& o p e r a t o r ( ) ( i n t i , i n t j ){ c o n s t T g e t ( i n t i , i n t j ){ // g e t and s e t e l e m e n t ; // Any b e t t e r i d e a ? i would l i k e t o u n i f y t h e g e t and o p e r a t o r ( ) // f u n c t i o n s . // Problem i s t h a t operator () always passes a r e f e r e n c e or c r e a t e s // one . v o i d mapToMxArray ( mxArray ∗ & i n ) // C r e a t e s a s p a r s e mxArray and c o p i e s d a t a i n t o 6 it .
© Copyright 2024