// Copyright (C) 2012 Massachusetts Institute of Technology, Lincoln Laboratory // License: Boost Software License See LICENSE.txt for the full license. // Authors: Davis E. King (davis@dlib.net) /* READ THIS FIRST ###### ###### ###### ###### ###### ###### ###### ###### ###### ###### ###### ###### ###### \############/ \##########/ \########/ \######/ \####/ \##/ \/ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! See example_mex_function.cpp for a discussion of how to use the mex wrapper. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! /\ /##\ /####\ /######\ /########\ /##########\ /############\ ###### ###### ###### ###### ###### ###### ###### ###### ###### ###### ###### ###### ###### READ THIS FIRST */ // Copyright (C) 2012 Massachusetts Institute of Technology, Lincoln Laboratory // License: Boost Software License See LICENSE.txt for the full license. // Authors: Davis E. King (davis@dlib.net) // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- // BEGIN IMPLEMENTATION DETAILS // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- #include "../matrix.h" #include "../array2d.h" #include "../array.h" #include "../image_transforms.h" #include "../is_kind.h" #include "../any.h" // for sig_traits #if defined(_MSC_VER) #define DLL_EXPORT_SYM __declspec(dllexport) #endif #include "mex.h" #include #include "call_matlab.h" // ---------------------------------------------------------------------------------------- #ifdef ARG_1_DEFAULT #define ELSE_ASSIGN_ARG_1 else A1 = ARG_1_DEFAULT; #else #define ELSE_ASSIGN_ARG_1 #endif #ifdef ARG_2_DEFAULT #define ELSE_ASSIGN_ARG_2 else A2 = ARG_2_DEFAULT; #else #define ELSE_ASSIGN_ARG_2 #endif #ifdef ARG_3_DEFAULT #define ELSE_ASSIGN_ARG_3 else A3 = ARG_3_DEFAULT; #else #define ELSE_ASSIGN_ARG_3 #endif #ifdef ARG_4_DEFAULT #define ELSE_ASSIGN_ARG_4 else A4 = ARG_4_DEFAULT; #else #define ELSE_ASSIGN_ARG_4 #endif #ifdef ARG_5_DEFAULT #define ELSE_ASSIGN_ARG_5 else A5 = ARG_5_DEFAULT; #else #define ELSE_ASSIGN_ARG_5 #endif #ifdef ARG_6_DEFAULT #define ELSE_ASSIGN_ARG_6 else A6 = ARG_6_DEFAULT; #else #define ELSE_ASSIGN_ARG_6 #endif #ifdef ARG_7_DEFAULT #define ELSE_ASSIGN_ARG_7 else A7 = ARG_7_DEFAULT; #else #define ELSE_ASSIGN_ARG_7 #endif #ifdef ARG_8_DEFAULT #define ELSE_ASSIGN_ARG_8 else A8 = ARG_8_DEFAULT; #else #define ELSE_ASSIGN_ARG_8 #endif #ifdef ARG_9_DEFAULT #define ELSE_ASSIGN_ARG_9 else A9 = ARG_9_DEFAULT; #else #define ELSE_ASSIGN_ARG_9 #endif #ifdef ARG_10_DEFAULT #define ELSE_ASSIGN_ARG_10 else A10 = ARG_10_DEFAULT; #else #define ELSE_ASSIGN_ARG_10 #endif // ---------------------------------------------------------------------------------------- namespace mex_binding { using namespace dlib; template struct is_input_type { const static unsigned long value = (!is_same_type::value && (!is_reference_type::value || is_const_type::value )) ? 1 : 0; }; template struct is_output_type { const static unsigned long value = (!is_same_type::value && is_reference_type::value && !is_const_type::value) ? 1 : 0; }; template struct funct_traits { const static unsigned long num_inputs = is_input_type::arg1_type>::value + is_input_type::arg2_type>::value + is_input_type::arg3_type>::value + is_input_type::arg4_type>::value + is_input_type::arg5_type>::value + is_input_type::arg6_type>::value + is_input_type::arg7_type>::value + is_input_type::arg8_type>::value + is_input_type::arg9_type>::value + is_input_type::arg10_type>::value; const static unsigned long num_outputs= is_output_type::arg1_type>::value + is_output_type::arg2_type>::value + is_output_type::arg3_type>::value + is_output_type::arg4_type>::value + is_output_type::arg5_type>::value + is_output_type::arg6_type>::value + is_output_type::arg7_type>::value + is_output_type::arg8_type>::value + is_output_type::arg9_type>::value + is_output_type::arg10_type>::value; }; // ---------------------------------------------------------------------------------------- template struct is_array_type { // true if T is std::vector or dlib::array const static bool value = is_std_vector::value || dlib::is_array::value; }; // ---------------------------------------------------------------------------------------- template < typename T, typename enabled = void > struct inner_type { typedef T type; }; template < typename T> struct inner_type::value || is_array2d::value || dlib::is_array::value >::type> { typedef typename T::type type; }; template < typename T> struct inner_type >::type> { typedef typename T::value_type type; }; // ------------------------------------------------------- struct invalid_args_exception { invalid_args_exception(const std::string& msg_): msg(msg_) {} std::string msg; }; // ------------------------------------------------------- template < typename matrix_type, typename EXP > typename dlib::enable_if_c::value && is_same_type::type,typename EXP::type>::value >::type assign_mat ( const long arg_idx, matrix_type& m, const matrix_exp& src ) { if (matrix_type::NR != 0 && matrix_type::NR != src.nc()) { std::ostringstream sout; sout << "Argument " << arg_idx+1 << " expects a matrix with " << matrix_type::NR << " rows but got one with " << src.nc(); mexErrMsgIdAndTxt("mex_function:validate_and_populate_arg", sout.str().c_str()); } if (matrix_type::NC != 0 && matrix_type::NC != src.nr()) { std::ostringstream sout; sout << "Argument " << arg_idx+1 << " expects a matrix with " << matrix_type::NC << " columns but got one with " << src.nr(); mexErrMsgIdAndTxt("mex_function:validate_and_populate_arg", sout.str().c_str()); } m = trans(src); } template < typename matrix_type, typename EXP > typename dlib::enable_if_c::value && is_same_type::type,typename EXP::type>::value >::type assign_mat ( const long arg_idx, matrix_type& m, const matrix_exp& src ) { assign_image(m , trans(src)); } template < typename matrix_type, typename EXP > typename disable_if_c<(is_array2d::value || is_matrix::value) && is_same_type::type,typename EXP::type>::value >::type assign_mat ( const long arg_idx, matrix_type& , const matrix_exp& ) { std::ostringstream sout; sout << "mex_function has some bug in it related to processing input argument " << arg_idx+1; mexErrMsgIdAndTxt("mex_function:validate_and_populate_arg", sout.str().c_str()); } // ------------------------------------------------------- template < typename T, typename U > typename dlib::enable_if_c::value || is_same_type::value >::type assign_scalar ( const long arg_idx, T& dest, const U& src ) { if (is_signed_type::value && src < 0 && is_unsigned_type::value) { std::ostringstream sout; sout << "Error, input argument " << arg_idx+1 << " must be a non-negative number."; mexErrMsgIdAndTxt("mex_function:validate_and_populate_arg", sout.str().c_str()); } else { dest = src; } } template < typename T, typename U > typename dlib::disable_if_c::value || is_same_type::value >::type assign_scalar ( const long arg_idx, T& , const U& ) { std::ostringstream sout; sout << "mex_function has some bug in it related to processing input argument " << arg_idx+1; mexErrMsgIdAndTxt("mex_function:validate_and_populate_arg", sout.str().c_str()); } // ------------------------------------------------------- void assign_function_handle ( const long arg_idx, function_handle& dest, const mxArray* src ) { const_cast(dest.h) = (void*)src; } template < typename T > void assign_function_handle ( const long arg_idx, T& , const mxArray* ) { std::ostringstream sout; sout << "mex_function has some bug in it related to processing input argument " << arg_idx+1; mexErrMsgIdAndTxt("mex_function:validate_and_populate_arg", sout.str().c_str()); } // ------------------------------------------------------- template < typename T > typename dlib::enable_if >::type assign_std_vector ( const long arg_idx, T& dest, const mxArray* src ) { const long nr = mxGetM(src); const long nc = mxGetN(src); typedef typename inner_type::type type; if (!mxIsCell(src)) { std::ostringstream sout; sout << " argument " << arg_idx+1 << " must be a cell array"; throw invalid_args_exception(sout.str()); } if (nr != 1 && nc != 1) { std::ostringstream sout; sout << " argument " << arg_idx+1 << " must be a cell array with exactly 1 row or 1 column (i.e. a row or column vector)"; throw invalid_args_exception(sout.str()); } const long size = nr*nc; dest.resize(size); for (unsigned long i = 0; i < dest.size(); ++i) { try { validate_and_populate_arg(i, mxGetCell(src, i), dest[i]); } catch (invalid_args_exception& e) { std::ostringstream sout; sout << "Error in argument " << arg_idx+1 << ": element " << i+1 << " of cell array not the expected type.\n"; sout << "\t" << e.msg; throw invalid_args_exception(sout.str()); } } } template < typename T > typename disable_if >::type assign_std_vector ( const long arg_idx, T& , const mxArray* ) { std::ostringstream sout; sout << "mex_function has some bug in it related to processing input argument " << arg_idx+1; mexErrMsgIdAndTxt("mex_function:validate_and_populate_arg", sout.str().c_str()); } // ------------------------------------------------------- template void assign_image ( const long arg_idx, T&, const dlib::uint8* data, long nr, long nc ) { std::ostringstream sout; sout << "mex_function has some bug in it related to processing input argument " << arg_idx+1; mexErrMsgIdAndTxt("mex_function:validate_and_populate_arg", sout.str().c_str()); } template void assign_image( const long , array2d& img, const dlib::uint8* data, long nr, long nc ) { img.set_size(nr, nc); for (long c = 0; c < img.nc(); ++c) for (long r = 0; r < img.nr(); ++r) img[r][c].red = *data++; for (long c = 0; c < img.nc(); ++c) for (long r = 0; r < img.nr(); ++r) img[r][c].green = *data++; for (long c = 0; c < img.nc(); ++c) for (long r = 0; r < img.nr(); ++r) img[r][c].blue = *data++; } // ------------------------------------------------------- template void validate_and_populate_arg ( long arg_idx, const mxArray *prhs, T& arg ) { using namespace mex_binding; if (is_built_in_scalar_type::value || is_same_type::value) { if( !(mxIsDouble(prhs) || mxIsSingle(prhs) || mxIsLogical(prhs) ) || mxIsComplex(prhs) || mxGetNumberOfElements(prhs)!=1 ) { std::ostringstream sout; sout << " argument " << arg_idx+1 << " must be a scalar"; throw invalid_args_exception(sout.str()); } assign_scalar(arg_idx, arg , mxGetScalar(prhs)); } else if (is_matrix::value || is_array2d::value) { typedef typename inner_type::type type; const int num_dims = mxGetNumberOfDimensions(prhs); const long nr = mxGetM(prhs); const long nc = mxGetN(prhs); if (is_same_type::value) { if (!(num_dims == 3 && mxGetDimensions(prhs)[2] == 3 && mxIsUint8(prhs))) { std::ostringstream sout; sout << " argument " << arg_idx+1 << " must be a 3-D NxMx3 image matrix of uint8"; throw invalid_args_exception(sout.str()); } const long rows = mxGetDimensions(prhs)[0]; const long cols = mxGetDimensions(prhs)[1]; assign_image(arg_idx, arg , (const dlib::uint8*)mxGetData(prhs), rows, cols); return; } if (num_dims != 2) { std::ostringstream sout; sout << " argument " << arg_idx+1 << " must be a 2-D matrix (got a " << num_dims << "-D matrix)"; throw invalid_args_exception(sout.str()); } if (is_same_type::value) { if (!mxIsDouble(prhs) || mxIsComplex(prhs)) { std::ostringstream sout; sout << " argument " << arg_idx+1 << " must be a matrix of doubles"; throw invalid_args_exception(sout.str()); } assign_mat(arg_idx, arg , pointer_to_matrix(mxGetPr(prhs), nc, nr)); } else if (is_same_type::value) { if (!mxIsSingle(prhs) || mxIsComplex(prhs)) { std::ostringstream sout; sout << " argument " << arg_idx+1 << " must be a matrix of single/float"; throw invalid_args_exception(sout.str()); } assign_mat(arg_idx, arg , pointer_to_matrix((const float*)mxGetData(prhs), nc, nr)); } else if (is_same_type::value) { if (!mxIsLogical(prhs)) { std::ostringstream sout; sout << " argument " << arg_idx+1 << " must be a matrix of logical elements."; throw invalid_args_exception(sout.str()); } assign_mat(arg_idx, arg , pointer_to_matrix((const bool*)mxGetData(prhs), nc, nr)); } else if (is_same_type::value) { if (!mxIsUint8(prhs) || mxIsComplex(prhs)) { std::ostringstream sout; sout << " argument " << arg_idx+1 << " must be a matrix of uint8"; throw invalid_args_exception(sout.str()); } assign_mat(arg_idx, arg , pointer_to_matrix((const dlib::uint8*)mxGetData(prhs), nc, nr)); } else if (is_same_type::value) { if (!mxIsInt8(prhs) || mxIsComplex(prhs)) { std::ostringstream sout; sout << " argument " << arg_idx+1 << " must be a matrix of int8"; throw invalid_args_exception(sout.str()); } assign_mat(arg_idx, arg , pointer_to_matrix((const dlib::int8*)mxGetData(prhs), nc, nr)); } else if (is_same_type::value || (is_same_type::value && sizeof(short) == sizeof(dlib::int16))) { if (!mxIsInt16(prhs) || mxIsComplex(prhs)) { std::ostringstream sout; sout << " argument " << arg_idx+1 << " must be a matrix of int16"; throw invalid_args_exception(sout.str()); } assign_mat(arg_idx, arg , pointer_to_matrix((const type*)mxGetData(prhs), nc, nr)); } else if (is_same_type::value || (is_same_type::value && sizeof(unsigned short) == sizeof(dlib::uint16))) { if (!mxIsUint16(prhs) || mxIsComplex(prhs)) { std::ostringstream sout; sout << " argument " << arg_idx+1 << " must be a matrix of uint16"; throw invalid_args_exception(sout.str()); } assign_mat(arg_idx, arg , pointer_to_matrix((const type*)mxGetData(prhs), nc, nr)); } else if (is_same_type::value || (is_same_type::value && sizeof(int) == sizeof(dlib::int32)) || (is_same_type::value && sizeof(long) == sizeof(dlib::int32))) { if (!mxIsInt32(prhs) || mxIsComplex(prhs)) { std::ostringstream sout; sout << " argument " << arg_idx+1 << " must be a matrix of int32"; throw invalid_args_exception(sout.str()); } assign_mat(arg_idx, arg , pointer_to_matrix((const type*)mxGetData(prhs), nc, nr)); } else if (is_same_type::value || (is_same_type::value && sizeof(unsigned int) == sizeof(dlib::uint32)) || (is_same_type::value && sizeof(unsigned long) == sizeof(dlib::uint32))) { if (!mxIsUint32(prhs) || mxIsComplex(prhs)) { std::ostringstream sout; sout << " argument " << arg_idx+1 << " must be a matrix of uint32"; throw invalid_args_exception(sout.str()); } assign_mat(arg_idx, arg , pointer_to_matrix((const type*)mxGetData(prhs), nc, nr)); } else if (is_same_type::value || (is_same_type::value && sizeof(unsigned int) == sizeof(dlib::uint64)) || (is_same_type::value && sizeof(unsigned long) == sizeof(dlib::uint64))) { if (!mxIsUint64(prhs) || mxIsComplex(prhs)) { std::ostringstream sout; sout << " argument " << arg_idx+1 << " must be a matrix of uint64"; throw invalid_args_exception(sout.str()); } assign_mat(arg_idx, arg , pointer_to_matrix((const type*)mxGetData(prhs), nc, nr)); } else if (is_same_type::value || (is_same_type::value && sizeof(int) == sizeof(dlib::int64)) || (is_same_type::value && sizeof(long) == sizeof(dlib::int64))) { if (!mxIsInt64(prhs) || mxIsComplex(prhs)) { std::ostringstream sout; sout << " argument " << arg_idx+1 << " must be a matrix of int64"; throw invalid_args_exception(sout.str()); } assign_mat(arg_idx, arg , pointer_to_matrix((const type*)mxGetData(prhs), nc, nr)); } else { mexErrMsgIdAndTxt("mex_function:validate_and_populate_arg", "mex_function uses unsupported matrix type"); } } else if (is_array_type::value) { assign_std_vector(arg_idx, arg, prhs); } else if (is_same_type::value) { if (!mxIsClass(prhs, "function_handle")) { std::ostringstream sout; sout << " argument " << arg_idx+1 << " must be a function handle."; throw invalid_args_exception(sout.str()); } assign_function_handle(arg_idx, arg, prhs); } else { mexErrMsgIdAndTxt("mex_function:validate_and_populate_arg", "mex_function uses unsupported input argument type"); } } void validate_and_populate_arg( long arg_idx, const mxArray *prhs, std::string& arg ) { if (!mxIsChar(prhs)) { std::ostringstream sout; sout << " argument " << arg_idx+1 << " must be a char string"; throw invalid_args_exception(sout.str()); } const long nr = mxGetM(prhs); const long nc = mxGetN(prhs); const long size = nr*nc; arg.resize(size+1); if (mxGetString(prhs, &arg[0], arg.size())) { std::ostringstream sout; sout << " argument " << arg_idx+1 << " encountered an error while calling mxGetString()"; throw invalid_args_exception(sout.str()); } arg.resize(size); } // ---------------------------------------------------------------------------------------- template typename dlib::enable_if >::type assign_image_to_matlab ( dlib::uint8* mat, const matrix_exp& item ) { for (long c = 0; c < item.nc(); ++c) for (long r = 0; r < item.nr(); ++r) *mat++ = item(r,c).red; for (long c = 0; c < item.nc(); ++c) for (long r = 0; r < item.nr(); ++r) *mat++ = item(r,c).green; for (long c = 0; c < item.nc(); ++c) for (long r = 0; r < item.nr(); ++r) *mat++ = item(r,c).blue; } template typename disable_if >::type assign_image_to_matlab ( T* mat, const matrix_exp& ) { mexErrMsgIdAndTxt("mex_function:validate_and_populate_arg", "mex_function uses unsupported output image argument type"); } template typename dlib::enable_if >::type assign_to_matlab( mxArray*& plhs, const T& item ) { typedef typename T::type type; type* mat = 0; if (is_same_type::value) { plhs = mxCreateDoubleMatrix(item.nr(), item.nc(), mxREAL); mat = (type*)mxGetPr(plhs); } else if (is_same_type::value ) { plhs = mxCreateNumericMatrix(item.nr(), item.nc(), mxSINGLE_CLASS, mxREAL); mat = (type*)mxGetData(plhs); } else if (is_same_type::value ) { plhs = mxCreateLogicalMatrix(item.nr(), item.nc()); mat = (type*)mxGetData(plhs); } else if (is_same_type::value ) { plhs = mxCreateNumericMatrix(item.nr(), item.nc(), mxUINT8_CLASS, mxREAL); mat = (type*)mxGetData(plhs); } else if (is_same_type::value ) { plhs = mxCreateNumericMatrix(item.nr(), item.nc(), mxINT8_CLASS, mxREAL); mat = (type*)mxGetData(plhs); } else if (is_same_type::value || (is_same_type::value && sizeof(short) == sizeof(dlib::int16))) { plhs = mxCreateNumericMatrix(item.nr(), item.nc(), mxINT16_CLASS, mxREAL); mat = (type*)mxGetData(plhs); } else if (is_same_type::value || (is_same_type::value && sizeof(unsigned short) == sizeof(dlib::uint16))) { plhs = mxCreateNumericMatrix(item.nr(), item.nc(), mxUINT16_CLASS, mxREAL); mat = (type*)mxGetData(plhs); } else if (is_same_type::value || (is_same_type::value && sizeof(long) == sizeof(dlib::int32))) { plhs = mxCreateNumericMatrix(item.nr(), item.nc(), mxINT32_CLASS, mxREAL); mat = (type*)mxGetData(plhs); } else if (is_same_type::value || (is_same_type::value && sizeof(unsigned long) == sizeof(dlib::uint32))) { plhs = mxCreateNumericMatrix(item.nr(), item.nc(), mxUINT32_CLASS, mxREAL); mat = (type*)mxGetData(plhs); } else if (is_same_type::value || (is_same_type::value && sizeof(unsigned long) == sizeof(dlib::uint64))) { plhs = mxCreateNumericMatrix(item.nr(), item.nc(), mxUINT64_CLASS, mxREAL); mat = (type*)mxGetData(plhs); } else if (is_same_type::value || (is_same_type::value && sizeof(long) == sizeof(dlib::int64))) { plhs = mxCreateNumericMatrix(item.nr(), item.nc(), mxINT64_CLASS, mxREAL); mat = (type*)mxGetData(plhs); } else if (is_same_type::value) { mwSize dims[3] = {item.nr(), item.nc(), 3}; plhs = mxCreateNumericArray(3, dims, mxUINT8_CLASS, mxREAL); assign_image_to_matlab((dlib::uint8*)mxGetData(plhs), item); return; } else { mexErrMsgIdAndTxt("mex_function:validate_and_populate_arg", "mex_function uses unsupported output argument type"); } for (long c = 0; c < item.nc(); ++c) { for ( long r= 0; r < item.nr(); ++r) { *mat++ = item(r,c); } } } void assign_to_matlab( mxArray*& plhs, const std::string& item ) { plhs = mxCreateString(item.c_str()); } template void assign_to_matlab( mxArray*& plhs, const array2d& item ) { assign_to_matlab(plhs,array_to_matrix(item)); } template typename dlib::enable_if >::type assign_to_matlab( mxArray*& plhs, const T& item ) { mwSize dims[1] = {item.size()}; plhs = mxCreateCellArray(1,dims); for (unsigned long i = 0; i < item.size(); ++i) { mxArray* next = 0; assign_to_matlab(next, item[i]); mxSetCell(plhs, i, next); } } template typename dlib::disable_if_c::value || is_array_type::value || is_same_type::value>::type assign_to_matlab( mxArray*& plhs, const T& item ) { plhs = mxCreateDoubleScalar(item); } void assign_to_matlab ( mxArray*& plhs, const char* str ) { assign_to_matlab(plhs, std::string(str)); } void assign_to_matlab( mxArray*& plhs, const function_handle& h ) { } // ---------------------------------------------------------------------------------------- template < unsigned long num_args > struct call_mex_function_helper; template <> struct call_mex_function_helper<1> { template void callit( const funct& , int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[] ) const { typedef typename sig_traits::arg1_type arg1_type; typename basic_type::type A1; int i = 0; if (i < nrhs && is_input_type::value) {validate_and_populate_arg(i,prhs[i],A1); ++i;} ELSE_ASSIGN_ARG_1; mex_function(A1); i = 0; if (is_output_type::value) {assign_to_matlab(plhs[i],A1); ++i;} } }; template <> struct call_mex_function_helper<2> { template void callit( const funct& , int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[] ) const { typedef typename sig_traits::arg1_type arg1_type; typedef typename sig_traits::arg2_type arg2_type; typename basic_type::type A1; typename basic_type::type A2; int i = 0; if (i < nrhs && is_input_type::value) {validate_and_populate_arg(i,prhs[i],A1); ++i;} ELSE_ASSIGN_ARG_1; if (i < nrhs && is_input_type::value) {validate_and_populate_arg(i,prhs[i],A2); ++i;} ELSE_ASSIGN_ARG_2; mex_function(A1,A2); i = 0; if (is_output_type::value) {assign_to_matlab(plhs[i],A1); ++i;} if (is_output_type::value) {assign_to_matlab(plhs[i],A2); ++i;} } }; template <> struct call_mex_function_helper<3> { template void callit( const funct& , int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[] ) const { typedef typename sig_traits::arg1_type arg1_type; typedef typename sig_traits::arg2_type arg2_type; typedef typename sig_traits::arg3_type arg3_type; typename basic_type::type A1; typename basic_type::type A2; typename basic_type::type A3; int i = 0; if (i < nrhs && is_input_type::value) {validate_and_populate_arg(i,prhs[i],A1); ++i;} ELSE_ASSIGN_ARG_1; if (i < nrhs && is_input_type::value) {validate_and_populate_arg(i,prhs[i],A2); ++i;} ELSE_ASSIGN_ARG_2; if (i < nrhs && is_input_type::value) {validate_and_populate_arg(i,prhs[i],A3); ++i;} ELSE_ASSIGN_ARG_3; mex_function(A1,A2,A3); i = 0; if (is_output_type::value) {assign_to_matlab(plhs[i],A1); ++i;} if (is_output_type::value) {assign_to_matlab(plhs[i],A2); ++i;} if (is_output_type::value) {assign_to_matlab(plhs[i],A3); ++i;} } }; template <> struct call_mex_function_helper<4> { template void callit( const funct& , int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[] ) const { typedef typename sig_traits::arg1_type arg1_type; typedef typename sig_traits::arg2_type arg2_type; typedef typename sig_traits::arg3_type arg3_type; typedef typename sig_traits::arg4_type arg4_type; typename basic_type::type A1; typename basic_type::type A2; typename basic_type::type A3; typename basic_type::type A4; int i = 0; if (i < nrhs && is_input_type::value) {validate_and_populate_arg(i,prhs[i],A1); ++i;} ELSE_ASSIGN_ARG_1; if (i < nrhs && is_input_type::value) {validate_and_populate_arg(i,prhs[i],A2); ++i;} ELSE_ASSIGN_ARG_2; if (i < nrhs && is_input_type::value) {validate_and_populate_arg(i,prhs[i],A3); ++i;} ELSE_ASSIGN_ARG_3; if (i < nrhs && is_input_type::value) {validate_and_populate_arg(i,prhs[i],A4); ++i;} ELSE_ASSIGN_ARG_4; mex_function(A1,A2,A3,A4); i = 0; if (is_output_type::value) {assign_to_matlab(plhs[i],A1); ++i;} if (is_output_type::value) {assign_to_matlab(plhs[i],A2); ++i;} if (is_output_type::value) {assign_to_matlab(plhs[i],A3); ++i;} if (is_output_type::value) {assign_to_matlab(plhs[i],A4); ++i;} } }; template <> struct call_mex_function_helper<5> { template void callit( const funct& , int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[] ) const { typedef typename sig_traits::arg1_type arg1_type; typedef typename sig_traits::arg2_type arg2_type; typedef typename sig_traits::arg3_type arg3_type; typedef typename sig_traits::arg4_type arg4_type; typedef typename sig_traits::arg5_type arg5_type; typename basic_type::type A1; typename basic_type::type A2; typename basic_type::type A3; typename basic_type::type A4; typename basic_type::type A5; int i = 0; if (i < nrhs && is_input_type::value) {validate_and_populate_arg(i,prhs[i],A1); ++i;} ELSE_ASSIGN_ARG_1; if (i < nrhs && is_input_type::value) {validate_and_populate_arg(i,prhs[i],A2); ++i;} ELSE_ASSIGN_ARG_2; if (i < nrhs && is_input_type::value) {validate_and_populate_arg(i,prhs[i],A3); ++i;} ELSE_ASSIGN_ARG_3; if (i < nrhs && is_input_type::value) {validate_and_populate_arg(i,prhs[i],A4); ++i;} ELSE_ASSIGN_ARG_4; if (i < nrhs && is_input_type::value) {validate_and_populate_arg(i,prhs[i],A5); ++i;} ELSE_ASSIGN_ARG_5; mex_function(A1,A2,A3,A4,A5); i = 0; if (is_output_type::value) {assign_to_matlab(plhs[i],A1); ++i;} if (is_output_type::value) {assign_to_matlab(plhs[i],A2); ++i;} if (is_output_type::value) {assign_to_matlab(plhs[i],A3); ++i;} if (is_output_type::value) {assign_to_matlab(plhs[i],A4); ++i;} if (is_output_type::value) {assign_to_matlab(plhs[i],A5); ++i;} } }; template <> struct call_mex_function_helper<6> { template void callit( const funct& , int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[] ) const { typedef typename sig_traits::arg1_type arg1_type; typedef typename sig_traits::arg2_type arg2_type; typedef typename sig_traits::arg3_type arg3_type; typedef typename sig_traits::arg4_type arg4_type; typedef typename sig_traits::arg5_type arg5_type; typedef typename sig_traits::arg6_type arg6_type; typename basic_type::type A1; typename basic_type::type A2; typename basic_type::type A3; typename basic_type::type A4; typename basic_type::type A5; typename basic_type::type A6; int i = 0; if (i < nrhs && is_input_type::value) {validate_and_populate_arg(i,prhs[i],A1); ++i;} ELSE_ASSIGN_ARG_1; if (i < nrhs && is_input_type::value) {validate_and_populate_arg(i,prhs[i],A2); ++i;} ELSE_ASSIGN_ARG_2; if (i < nrhs && is_input_type::value) {validate_and_populate_arg(i,prhs[i],A3); ++i;} ELSE_ASSIGN_ARG_3; if (i < nrhs && is_input_type::value) {validate_and_populate_arg(i,prhs[i],A4); ++i;} ELSE_ASSIGN_ARG_4; if (i < nrhs && is_input_type::value) {validate_and_populate_arg(i,prhs[i],A5); ++i;} ELSE_ASSIGN_ARG_5; if (i < nrhs && is_input_type::value) {validate_and_populate_arg(i,prhs[i],A6); ++i;} ELSE_ASSIGN_ARG_6; mex_function(A1,A2,A3,A4,A5,A6); i = 0; if (is_output_type::value) {assign_to_matlab(plhs[i],A1); ++i;} if (is_output_type::value) {assign_to_matlab(plhs[i],A2); ++i;} if (is_output_type::value) {assign_to_matlab(plhs[i],A3); ++i;} if (is_output_type::value) {assign_to_matlab(plhs[i],A4); ++i;} if (is_output_type::value) {assign_to_matlab(plhs[i],A5); ++i;} if (is_output_type::value) {assign_to_matlab(plhs[i],A6); ++i;} } }; template <> struct call_mex_function_helper<7> { template void callit( const funct& , int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[] ) const { typedef typename sig_traits::arg1_type arg1_type; typedef typename sig_traits::arg2_type arg2_type; typedef typename sig_traits::arg3_type arg3_type; typedef typename sig_traits::arg4_type arg4_type; typedef typename sig_traits::arg5_type arg5_type; typedef typename sig_traits::arg6_type arg6_type; typedef typename sig_traits::arg7_type arg7_type; typename basic_type::type A1; typename basic_type::type A2; typename basic_type::type A3; typename basic_type::type A4; typename basic_type::type A5; typename basic_type::type A6; typename basic_type::type A7; int i = 0; if (i < nrhs && is_input_type::value) {validate_and_populate_arg(i,prhs[i],A1); ++i;} ELSE_ASSIGN_ARG_1; if (i < nrhs && is_input_type::value) {validate_and_populate_arg(i,prhs[i],A2); ++i;} ELSE_ASSIGN_ARG_2; if (i < nrhs && is_input_type::value) {validate_and_populate_arg(i,prhs[i],A3); ++i;} ELSE_ASSIGN_ARG_3; if (i < nrhs && is_input_type::value) {validate_and_populate_arg(i,prhs[i],A4); ++i;} ELSE_ASSIGN_ARG_4; if (i < nrhs && is_input_type::value) {validate_and_populate_arg(i,prhs[i],A5); ++i;} ELSE_ASSIGN_ARG_5; if (i < nrhs && is_input_type::value) {validate_and_populate_arg(i,prhs[i],A6); ++i;} ELSE_ASSIGN_ARG_6; if (i < nrhs && is_input_type::value) {validate_and_populate_arg(i,prhs[i],A7); ++i;} ELSE_ASSIGN_ARG_7; mex_function(A1,A2,A3,A4,A5,A6,A7); i = 0; if (is_output_type::value) {assign_to_matlab(plhs[i],A1); ++i;} if (is_output_type::value) {assign_to_matlab(plhs[i],A2); ++i;} if (is_output_type::value) {assign_to_matlab(plhs[i],A3); ++i;} if (is_output_type::value) {assign_to_matlab(plhs[i],A4); ++i;} if (is_output_type::value) {assign_to_matlab(plhs[i],A5); ++i;} if (is_output_type::value) {assign_to_matlab(plhs[i],A6); ++i;} if (is_output_type::value) {assign_to_matlab(plhs[i],A7); ++i;} } }; template <> struct call_mex_function_helper<8> { template void callit( const funct& , int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[] ) const { typedef typename sig_traits::arg1_type arg1_type; typedef typename sig_traits::arg2_type arg2_type; typedef typename sig_traits::arg3_type arg3_type; typedef typename sig_traits::arg4_type arg4_type; typedef typename sig_traits::arg5_type arg5_type; typedef typename sig_traits::arg6_type arg6_type; typedef typename sig_traits::arg7_type arg7_type; typedef typename sig_traits::arg8_type arg8_type; typename basic_type::type A1; typename basic_type::type A2; typename basic_type::type A3; typename basic_type::type A4; typename basic_type::type A5; typename basic_type::type A6; typename basic_type::type A7; typename basic_type::type A8; int i = 0; if (i < nrhs && is_input_type::value) {validate_and_populate_arg(i,prhs[i],A1); ++i;} ELSE_ASSIGN_ARG_1; if (i < nrhs && is_input_type::value) {validate_and_populate_arg(i,prhs[i],A2); ++i;} ELSE_ASSIGN_ARG_2; if (i < nrhs && is_input_type::value) {validate_and_populate_arg(i,prhs[i],A3); ++i;} ELSE_ASSIGN_ARG_3; if (i < nrhs && is_input_type::value) {validate_and_populate_arg(i,prhs[i],A4); ++i;} ELSE_ASSIGN_ARG_4; if (i < nrhs && is_input_type::value) {validate_and_populate_arg(i,prhs[i],A5); ++i;} ELSE_ASSIGN_ARG_5; if (i < nrhs && is_input_type::value) {validate_and_populate_arg(i,prhs[i],A6); ++i;} ELSE_ASSIGN_ARG_6; if (i < nrhs && is_input_type::value) {validate_and_populate_arg(i,prhs[i],A7); ++i;} ELSE_ASSIGN_ARG_7; if (i < nrhs && is_input_type::value) {validate_and_populate_arg(i,prhs[i],A8); ++i;} ELSE_ASSIGN_ARG_8; mex_function(A1,A2,A3,A4,A5,A6,A7,A8); i = 0; if (is_output_type::value) {assign_to_matlab(plhs[i],A1); ++i;} if (is_output_type::value) {assign_to_matlab(plhs[i],A2); ++i;} if (is_output_type::value) {assign_to_matlab(plhs[i],A3); ++i;} if (is_output_type::value) {assign_to_matlab(plhs[i],A4); ++i;} if (is_output_type::value) {assign_to_matlab(plhs[i],A5); ++i;} if (is_output_type::value) {assign_to_matlab(plhs[i],A6); ++i;} if (is_output_type::value) {assign_to_matlab(plhs[i],A7); ++i;} if (is_output_type::value) {assign_to_matlab(plhs[i],A8); ++i;} } }; template <> struct call_mex_function_helper<9> { template void callit( const funct& , int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[] ) const { typedef typename sig_traits::arg1_type arg1_type; typedef typename sig_traits::arg2_type arg2_type; typedef typename sig_traits::arg3_type arg3_type; typedef typename sig_traits::arg4_type arg4_type; typedef typename sig_traits::arg5_type arg5_type; typedef typename sig_traits::arg6_type arg6_type; typedef typename sig_traits::arg7_type arg7_type; typedef typename sig_traits::arg8_type arg8_type; typedef typename sig_traits::arg9_type arg9_type; typename basic_type::type A1; typename basic_type::type A2; typename basic_type::type A3; typename basic_type::type A4; typename basic_type::type A5; typename basic_type::type A6; typename basic_type::type A7; typename basic_type::type A8; typename basic_type::type A9; int i = 0; if (i < nrhs && is_input_type::value) {validate_and_populate_arg(i,prhs[i],A1); ++i;} ELSE_ASSIGN_ARG_1; if (i < nrhs && is_input_type::value) {validate_and_populate_arg(i,prhs[i],A2); ++i;} ELSE_ASSIGN_ARG_2; if (i < nrhs && is_input_type::value) {validate_and_populate_arg(i,prhs[i],A3); ++i;} ELSE_ASSIGN_ARG_3; if (i < nrhs && is_input_type::value) {validate_and_populate_arg(i,prhs[i],A4); ++i;} ELSE_ASSIGN_ARG_4; if (i < nrhs && is_input_type::value) {validate_and_populate_arg(i,prhs[i],A5); ++i;} ELSE_ASSIGN_ARG_5; if (i < nrhs && is_input_type::value) {validate_and_populate_arg(i,prhs[i],A6); ++i;} ELSE_ASSIGN_ARG_6; if (i < nrhs && is_input_type::value) {validate_and_populate_arg(i,prhs[i],A7); ++i;} ELSE_ASSIGN_ARG_7; if (i < nrhs && is_input_type::value) {validate_and_populate_arg(i,prhs[i],A8); ++i;} ELSE_ASSIGN_ARG_8; if (i < nrhs && is_input_type::value) {validate_and_populate_arg(i,prhs[i],A9); ++i;} ELSE_ASSIGN_ARG_9; mex_function(A1,A2,A3,A4,A5,A6,A7,A8,A9); i = 0; if (is_output_type::value) {assign_to_matlab(plhs[i],A1); ++i;} if (is_output_type::value) {assign_to_matlab(plhs[i],A2); ++i;} if (is_output_type::value) {assign_to_matlab(plhs[i],A3); ++i;} if (is_output_type::value) {assign_to_matlab(plhs[i],A4); ++i;} if (is_output_type::value) {assign_to_matlab(plhs[i],A5); ++i;} if (is_output_type::value) {assign_to_matlab(plhs[i],A6); ++i;} if (is_output_type::value) {assign_to_matlab(plhs[i],A7); ++i;} if (is_output_type::value) {assign_to_matlab(plhs[i],A8); ++i;} if (is_output_type::value) {assign_to_matlab(plhs[i],A9); ++i;} } }; template <> struct call_mex_function_helper<10> { template void callit( const funct& , int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[] ) const { typedef typename sig_traits::arg1_type arg1_type; typedef typename sig_traits::arg2_type arg2_type; typedef typename sig_traits::arg3_type arg3_type; typedef typename sig_traits::arg4_type arg4_type; typedef typename sig_traits::arg5_type arg5_type; typedef typename sig_traits::arg6_type arg6_type; typedef typename sig_traits::arg7_type arg7_type; typedef typename sig_traits::arg8_type arg8_type; typedef typename sig_traits::arg9_type arg9_type; typedef typename sig_traits::arg10_type arg10_type; typename basic_type::type A1; typename basic_type::type A2; typename basic_type::type A3; typename basic_type::type A4; typename basic_type::type A5; typename basic_type::type A6; typename basic_type::type A7; typename basic_type::type A8; typename basic_type::type A9; typename basic_type::type A10; int i = 0; if (i < nrhs && is_input_type::value) {validate_and_populate_arg(i,prhs[i],A1); ++i;} ELSE_ASSIGN_ARG_1; if (i < nrhs && is_input_type::value) {validate_and_populate_arg(i,prhs[i],A2); ++i;} ELSE_ASSIGN_ARG_2; if (i < nrhs && is_input_type::value) {validate_and_populate_arg(i,prhs[i],A3); ++i;} ELSE_ASSIGN_ARG_3; if (i < nrhs && is_input_type::value) {validate_and_populate_arg(i,prhs[i],A4); ++i;} ELSE_ASSIGN_ARG_4; if (i < nrhs && is_input_type::value) {validate_and_populate_arg(i,prhs[i],A5); ++i;} ELSE_ASSIGN_ARG_5; if (i < nrhs && is_input_type::value) {validate_and_populate_arg(i,prhs[i],A6); ++i;} ELSE_ASSIGN_ARG_6; if (i < nrhs && is_input_type::value) {validate_and_populate_arg(i,prhs[i],A7); ++i;} ELSE_ASSIGN_ARG_7; if (i < nrhs && is_input_type::value) {validate_and_populate_arg(i,prhs[i],A8); ++i;} ELSE_ASSIGN_ARG_8; if (i < nrhs && is_input_type::value) {validate_and_populate_arg(i,prhs[i],A9); ++i;} ELSE_ASSIGN_ARG_9; if (i < nrhs && is_input_type::value) {validate_and_populate_arg(i,prhs[i],A10); ++i;} ELSE_ASSIGN_ARG_10; mex_function(A1,A2,A3,A4,A5,A6,A7,A8,A9,A10); i = 0; if (is_output_type::value) {assign_to_matlab(plhs[i],A1); ++i;} if (is_output_type::value) {assign_to_matlab(plhs[i],A2); ++i;} if (is_output_type::value) {assign_to_matlab(plhs[i],A3); ++i;} if (is_output_type::value) {assign_to_matlab(plhs[i],A4); ++i;} if (is_output_type::value) {assign_to_matlab(plhs[i],A5); ++i;} if (is_output_type::value) {assign_to_matlab(plhs[i],A6); ++i;} if (is_output_type::value) {assign_to_matlab(plhs[i],A7); ++i;} if (is_output_type::value) {assign_to_matlab(plhs[i],A8); ++i;} if (is_output_type::value) {assign_to_matlab(plhs[i],A9); ++i;} if (is_output_type::value) {assign_to_matlab(plhs[i],A10); ++i;} } }; // ---------------------------------------------------------------------------------------- template < typename funct > void call_mex_function ( const funct& f, int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[] ) { const long expected_nrhs = funct_traits::num_inputs; const long expected_nlhs = funct_traits::num_outputs; const long expected_args = expected_nrhs + expected_nlhs; long defaulted_args = 0; #ifdef ARG_1_DEFAULT ++defaulted_args; // You can only set an argument's default value if it is an input argument. COMPILE_TIME_ASSERT(is_input_type::arg1_type>::value); #ifndef ARG_2_DEFAULT // You can't define a default for argument 1 if you don't define one for argument 2 also. COMPILE_TIME_ASSERT(expected_args < 2); #endif COMPILE_TIME_ASSERT(1 <= expected_args); // You can't define a default for an argument that doesn't exist. #endif #ifdef ARG_2_DEFAULT ++defaulted_args; // You can only set an argument's default value if it is an input argument. COMPILE_TIME_ASSERT(is_input_type::arg2_type>::value); #ifndef ARG_3_DEFAULT // You can't define a default for argument 2 if you don't define one for argument 3 also. COMPILE_TIME_ASSERT(expected_args < 3); #endif COMPILE_TIME_ASSERT(2 <= expected_args); // You can't define a default for an argument that doesn't exist. #endif #ifdef ARG_3_DEFAULT ++defaulted_args; // You can only set an argument's default value if it is an input argument. COMPILE_TIME_ASSERT(is_input_type::arg3_type>::value); #ifndef ARG_4_DEFAULT // You can't define a default for argument 3 if you don't define one for argument 4 also. COMPILE_TIME_ASSERT(expected_args < 4); #endif COMPILE_TIME_ASSERT(3 <= expected_args); // You can't define a default for an argument that doesn't exist. #endif #ifdef ARG_4_DEFAULT ++defaulted_args; // You can only set an argument's default value if it is an input argument. COMPILE_TIME_ASSERT(is_input_type::arg4_type>::value); #ifndef ARG_5_DEFAULT // You can't define a default for argument 4 if you don't define one for argument 5 also. COMPILE_TIME_ASSERT(expected_args < 5); #endif COMPILE_TIME_ASSERT(4 <= expected_args); // You can't define a default for an argument that doesn't exist. #endif #ifdef ARG_5_DEFAULT ++defaulted_args; // You can only set an argument's default value if it is an input argument. COMPILE_TIME_ASSERT(is_input_type::arg5_type>::value); #ifndef ARG_6_DEFAULT // You can't define a default for argument 5 if you don't define one for argument 6 also. COMPILE_TIME_ASSERT(expected_args < 6); #endif COMPILE_TIME_ASSERT(5 <= expected_args); // You can't define a default for an argument that doesn't exist. #endif #ifdef ARG_6_DEFAULT ++defaulted_args; // You can only set an argument's default value if it is an input argument. COMPILE_TIME_ASSERT(is_input_type::arg6_type>::value); #ifndef ARG_7_DEFAULT // You can't define a default for argument 6 if you don't define one for argument 7 also. COMPILE_TIME_ASSERT(expected_args < 7); #endif COMPILE_TIME_ASSERT(6 <= expected_args); // You can't define a default for an argument that doesn't exist. #endif #ifdef ARG_7_DEFAULT ++defaulted_args; // You can only set an argument's default value if it is an input argument. COMPILE_TIME_ASSERT(is_input_type::arg7_type>::value); #ifndef ARG_8_DEFAULT // You can't define a default for argument 7 if you don't define one for argument 8 also. COMPILE_TIME_ASSERT(expected_args < 8); #endif COMPILE_TIME_ASSERT(7 <= expected_args); // You can't define a default for an argument that doesn't exist. #endif #ifdef ARG_8_DEFAULT ++defaulted_args; // You can only set an argument's default value if it is an input argument. COMPILE_TIME_ASSERT(is_input_type::arg8_type>::value); #ifndef ARG_9_DEFAULT // You can't define a default for argument 8 if you don't define one for argument 9 also. COMPILE_TIME_ASSERT(expected_args < 9); #endif COMPILE_TIME_ASSERT(8 <= expected_args); // You can't define a default for an argument that doesn't exist. #endif #ifdef ARG_9_DEFAULT ++defaulted_args; // You can only set an argument's default value if it is an input argument. COMPILE_TIME_ASSERT(is_input_type::arg9_type>::value); #ifndef ARG_10_DEFAULT // You can't define a default for argument 9 if you don't define one for argument 10 also. COMPILE_TIME_ASSERT(expected_args < 10); #endif COMPILE_TIME_ASSERT(9 <= expected_args); // You can't define a default for an argument that doesn't exist. #endif #ifdef ARG_10_DEFAULT ++defaulted_args; // You can only set an argument's default value if it is an input argument. COMPILE_TIME_ASSERT(is_input_type::arg10_type>::value); COMPILE_TIME_ASSERT(10 <= expected_args); // You can't define a default for an argument that doesn't exist. #endif /* check for proper number of arguments */ if(nrhs > expected_nrhs || nrhs < expected_nrhs - defaulted_args) { std::ostringstream sout; sout << "Expected between " << expected_nrhs-defaulted_args << " and " << expected_nrhs << " input arguments, got " << nrhs << "."; mexErrMsgIdAndTxt("mex_function:nrhs", sout.str().c_str()); } if (nlhs > expected_nlhs) { std::ostringstream sout; sout << "Expected at most " << expected_nlhs << " output arguments, got " << nlhs << "."; mexErrMsgIdAndTxt("mex_function:nlhs", sout.str().c_str()); } try { call_mex_function_helper::num_args> helper; helper.callit(f, nlhs, plhs, nrhs, prhs); } catch (invalid_args_exception& e) { mexErrMsgIdAndTxt("mex_function:validate_and_populate_arg", ("Input" + e.msg).c_str()); } catch (dlib::error& e) { mexErrMsgIdAndTxt("mex_function:error", e.what()); } } // ---------------------------------------------------------------------------------------- class mex_streambuf : public std::streambuf { public: mex_streambuf ( ) { buf.resize(1000); setp(&buf[0], &buf[0] + buf.size()-2); // make cout send data to mex_streambuf std::cout.rdbuf(this); } protected: int sync ( ) { int num = static_cast(pptr()-pbase()); if (num != 0) { buf[num] = 0; // null terminate the string mexPrintf("%s",&buf[0]); mexEvalString("drawnow"); // flush print to screen pbump(-num); } return 0; } int_type overflow ( int_type c ) { if (c != EOF) { *pptr() = c; pbump(1); } sync(); return c; } private: std::vector buf; }; // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- template void setup_input_args ( mxArray*& array, const T& item, int& nrhs ) { assign_to_matlab(array, item); ++nrhs; } void setup_input_args ( mxArray*& array, const function_handle& item, int& nrhs ) { array = static_cast(item.h); ++nrhs; } template void setup_input_args ( mxArray*& array, const output_decorator& item, int& nrhs ) { } template void setup_output_args ( const std::string& function_name, mxArray* array, const T& item, int& nrhs ) { } template void setup_output_args ( const std::string& function_name, mxArray* array, const output_decorator& item, int& i ) { try { validate_and_populate_arg(i,array,const_cast(item.item)); ++i; } catch (invalid_args_exception& e) { throw dlib::error("Error occurred calling MATLAB function '" + function_name + "' from mex file. \n" "The MATLAB function didn't return what we expected it to. \nIn particular, return" + e.msg); } } void call_matlab_for_real ( int nlhs, mxArray* plhs[], int nrhs, mxArray* prhs[], const std::string& function_name ) { int status = mexCallMATLAB(nlhs, plhs, nrhs, prhs, function_name.c_str()); if (status) { throw dlib::error("Error, an exception was thrown when we tried to call the MATLAB function '" + function_name + "'."); } } // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- } // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- void call_matlab ( const std::string& function_name ) { using namespace mex_binding; call_matlab_for_real(0,NULL,0,NULL, function_name); } template void free_callback_resources ( int nlhs, mxArray* plhs[], int nrhs, mxArray* prhs[] ) { // free resources for (int i = 0; i < nlhs; ++i) mxDestroyArray(plhs[i]); for (int i = 0; i < nrhs; ++i) { // don't call mxDestroyArray() on function handles (which should only ever be in prhs[0]) if (i == 0 && dlib::is_same_type::value) continue; mxDestroyArray(prhs[i]); } } template < typename T1 > void call_matlab ( const std::string& function_name, const T1& A1 ) { using namespace mex_binding; const int num_args = 1; mxArray* plhs[num_args] = {0}; mxArray* prhs[num_args] = {0}; int nrhs = 0; setup_input_args(prhs[nrhs], A1, nrhs); const int nlhs = num_args - nrhs; call_matlab_for_real(nlhs,plhs,nrhs,prhs, function_name); int i = 0; setup_output_args(function_name, plhs[i], A1, i); free_callback_resources(nlhs,plhs,nrhs,prhs); } template < typename T1, typename T2 > void call_matlab ( const std::string& function_name, const T1& A1, const T2& A2 ) { using namespace mex_binding; const int num_args = 2; mxArray* plhs[num_args] = {0}; mxArray* prhs[num_args] = {0}; int nrhs = 0; setup_input_args(prhs[nrhs], A1, nrhs); setup_input_args(prhs[nrhs], A2, nrhs); const int nlhs = num_args - nrhs; call_matlab_for_real(nlhs,plhs,nrhs,prhs, function_name); int i = 0; setup_output_args(function_name, plhs[i], A1, i); setup_output_args(function_name, plhs[i], A2, i); free_callback_resources(nlhs,plhs,nrhs,prhs); } template < typename T1, typename T2, typename T3 > void call_matlab ( const std::string& function_name, const T1& A1, const T2& A2, const T3& A3 ) { using namespace mex_binding; const int num_args = 3; mxArray* plhs[num_args] = {0}; mxArray* prhs[num_args] = {0}; int nrhs = 0; setup_input_args(prhs[nrhs], A1, nrhs); setup_input_args(prhs[nrhs], A2, nrhs); setup_input_args(prhs[nrhs], A3, nrhs); const int nlhs = num_args - nrhs; call_matlab_for_real(nlhs,plhs,nrhs,prhs, function_name); int i = 0; setup_output_args(function_name, plhs[i], A1, i); setup_output_args(function_name, plhs[i], A2, i); setup_output_args(function_name, plhs[i], A3, i); free_callback_resources(nlhs,plhs,nrhs,prhs); } template < typename T1, typename T2, typename T3, typename T4 > void call_matlab ( const std::string& function_name, const T1& A1, const T2& A2, const T3& A3, const T4& A4 ) { using namespace mex_binding; const int num_args = 4; mxArray* plhs[num_args] = {0}; mxArray* prhs[num_args] = {0}; int nrhs = 0; setup_input_args(prhs[nrhs], A1, nrhs); setup_input_args(prhs[nrhs], A2, nrhs); setup_input_args(prhs[nrhs], A3, nrhs); setup_input_args(prhs[nrhs], A4, nrhs); const int nlhs = num_args - nrhs; call_matlab_for_real(nlhs,plhs,nrhs,prhs, function_name); int i = 0; setup_output_args(function_name, plhs[i], A1, i); setup_output_args(function_name, plhs[i], A2, i); setup_output_args(function_name, plhs[i], A3, i); setup_output_args(function_name, plhs[i], A4, i); free_callback_resources(nlhs,plhs,nrhs,prhs); } template < typename T1, typename T2, typename T3, typename T4, typename T5 > void call_matlab ( const std::string& function_name, const T1& A1, const T2& A2, const T3& A3, const T4& A4, const T5& A5 ) { using namespace mex_binding; const int num_args = 5; mxArray* plhs[num_args] = {0}; mxArray* prhs[num_args] = {0}; int nrhs = 0; setup_input_args(prhs[nrhs], A1, nrhs); setup_input_args(prhs[nrhs], A2, nrhs); setup_input_args(prhs[nrhs], A3, nrhs); setup_input_args(prhs[nrhs], A4, nrhs); setup_input_args(prhs[nrhs], A5, nrhs); const int nlhs = num_args - nrhs; call_matlab_for_real(nlhs,plhs,nrhs,prhs, function_name); int i = 0; setup_output_args(function_name, plhs[i], A1, i); setup_output_args(function_name, plhs[i], A2, i); setup_output_args(function_name, plhs[i], A3, i); setup_output_args(function_name, plhs[i], A4, i); setup_output_args(function_name, plhs[i], A5, i); free_callback_resources(nlhs,plhs,nrhs,prhs); } template < typename T1, typename T2, typename T3, typename T4, typename T5, typename T6 > void call_matlab ( const std::string& function_name, const T1& A1, const T2& A2, const T3& A3, const T4& A4, const T5& A5, const T6& A6 ) { using namespace mex_binding; const int num_args = 6; mxArray* plhs[num_args] = {0}; mxArray* prhs[num_args] = {0}; int nrhs = 0; setup_input_args(prhs[nrhs], A1, nrhs); setup_input_args(prhs[nrhs], A2, nrhs); setup_input_args(prhs[nrhs], A3, nrhs); setup_input_args(prhs[nrhs], A4, nrhs); setup_input_args(prhs[nrhs], A5, nrhs); setup_input_args(prhs[nrhs], A6, nrhs); const int nlhs = num_args - nrhs; call_matlab_for_real(nlhs,plhs,nrhs,prhs, function_name); int i = 0; setup_output_args(function_name, plhs[i], A1, i); setup_output_args(function_name, plhs[i], A2, i); setup_output_args(function_name, plhs[i], A3, i); setup_output_args(function_name, plhs[i], A4, i); setup_output_args(function_name, plhs[i], A5, i); setup_output_args(function_name, plhs[i], A6, i); free_callback_resources(nlhs,plhs,nrhs,prhs); } template < typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7 > void call_matlab ( const std::string& function_name, const T1& A1, const T2& A2, const T3& A3, const T4& A4, const T5& A5, const T6& A6, const T7& A7 ) { using namespace mex_binding; const int num_args = 7; mxArray* plhs[num_args] = {0}; mxArray* prhs[num_args] = {0}; int nrhs = 0; setup_input_args(prhs[nrhs], A1, nrhs); setup_input_args(prhs[nrhs], A2, nrhs); setup_input_args(prhs[nrhs], A3, nrhs); setup_input_args(prhs[nrhs], A4, nrhs); setup_input_args(prhs[nrhs], A5, nrhs); setup_input_args(prhs[nrhs], A6, nrhs); setup_input_args(prhs[nrhs], A7, nrhs); const int nlhs = num_args - nrhs; call_matlab_for_real(nlhs,plhs,nrhs,prhs, function_name); int i = 0; setup_output_args(function_name, plhs[i], A1, i); setup_output_args(function_name, plhs[i], A2, i); setup_output_args(function_name, plhs[i], A3, i); setup_output_args(function_name, plhs[i], A4, i); setup_output_args(function_name, plhs[i], A5, i); setup_output_args(function_name, plhs[i], A6, i); setup_output_args(function_name, plhs[i], A7, i); free_callback_resources(nlhs,plhs,nrhs,prhs); } template < typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8 > void call_matlab ( const std::string& function_name, const T1& A1, const T2& A2, const T3& A3, const T4& A4, const T5& A5, const T6& A6, const T7& A7, const T8& A8 ) { using namespace mex_binding; const int num_args = 8; mxArray* plhs[num_args] = {0}; mxArray* prhs[num_args] = {0}; int nrhs = 0; setup_input_args(prhs[nrhs], A1, nrhs); setup_input_args(prhs[nrhs], A2, nrhs); setup_input_args(prhs[nrhs], A3, nrhs); setup_input_args(prhs[nrhs], A4, nrhs); setup_input_args(prhs[nrhs], A5, nrhs); setup_input_args(prhs[nrhs], A6, nrhs); setup_input_args(prhs[nrhs], A7, nrhs); setup_input_args(prhs[nrhs], A8, nrhs); const int nlhs = num_args - nrhs; call_matlab_for_real(nlhs,plhs,nrhs,prhs, function_name); int i = 0; setup_output_args(function_name, plhs[i], A1, i); setup_output_args(function_name, plhs[i], A2, i); setup_output_args(function_name, plhs[i], A3, i); setup_output_args(function_name, plhs[i], A4, i); setup_output_args(function_name, plhs[i], A5, i); setup_output_args(function_name, plhs[i], A6, i); setup_output_args(function_name, plhs[i], A7, i); setup_output_args(function_name, plhs[i], A8, i); free_callback_resources(nlhs,plhs,nrhs,prhs); } template < typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9 > void call_matlab ( const std::string& function_name, const T1& A1, const T2& A2, const T3& A3, const T4& A4, const T5& A5, const T6& A6, const T7& A7, const T8& A8, const T9& A9 ) { using namespace mex_binding; const int num_args = 9; mxArray* plhs[num_args] = {0}; mxArray* prhs[num_args] = {0}; int nrhs = 0; setup_input_args(prhs[nrhs], A1, nrhs); setup_input_args(prhs[nrhs], A2, nrhs); setup_input_args(prhs[nrhs], A3, nrhs); setup_input_args(prhs[nrhs], A4, nrhs); setup_input_args(prhs[nrhs], A5, nrhs); setup_input_args(prhs[nrhs], A6, nrhs); setup_input_args(prhs[nrhs], A7, nrhs); setup_input_args(prhs[nrhs], A8, nrhs); setup_input_args(prhs[nrhs], A9, nrhs); const int nlhs = num_args - nrhs; call_matlab_for_real(nlhs,plhs,nrhs,prhs, function_name); int i = 0; setup_output_args(function_name, plhs[i], A1, i); setup_output_args(function_name, plhs[i], A2, i); setup_output_args(function_name, plhs[i], A3, i); setup_output_args(function_name, plhs[i], A4, i); setup_output_args(function_name, plhs[i], A5, i); setup_output_args(function_name, plhs[i], A6, i); setup_output_args(function_name, plhs[i], A7, i); setup_output_args(function_name, plhs[i], A8, i); setup_output_args(function_name, plhs[i], A9, i); free_callback_resources(nlhs,plhs,nrhs,prhs); } template < typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10 > void call_matlab ( const std::string& function_name, const T1& A1, const T2& A2, const T3& A3, const T4& A4, const T5& A5, const T6& A6, const T7& A7, const T8& A8, const T9& A9, const T10& A10 ) { using namespace mex_binding; const int num_args = 10; mxArray* plhs[num_args] = {0}; mxArray* prhs[num_args] = {0}; int nrhs = 0; setup_input_args(prhs[nrhs], A1, nrhs); setup_input_args(prhs[nrhs], A2, nrhs); setup_input_args(prhs[nrhs], A3, nrhs); setup_input_args(prhs[nrhs], A4, nrhs); setup_input_args(prhs[nrhs], A5, nrhs); setup_input_args(prhs[nrhs], A6, nrhs); setup_input_args(prhs[nrhs], A7, nrhs); setup_input_args(prhs[nrhs], A8, nrhs); setup_input_args(prhs[nrhs], A10, nrhs); const int nlhs = num_args - nrhs; call_matlab_for_real(nlhs,plhs,nrhs,prhs, function_name); int i = 0; setup_output_args(function_name, plhs[i], A1, i); setup_output_args(function_name, plhs[i], A2, i); setup_output_args(function_name, plhs[i], A3, i); setup_output_args(function_name, plhs[i], A4, i); setup_output_args(function_name, plhs[i], A5, i); setup_output_args(function_name, plhs[i], A6, i); setup_output_args(function_name, plhs[i], A7, i); setup_output_args(function_name, plhs[i], A8, i); setup_output_args(function_name, plhs[i], A10, i); free_callback_resources(nlhs,plhs,nrhs,prhs); } // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- void call_matlab ( const function_handle& funct ) { call_matlab("feval", funct); } // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- /* The gateway function called by MATLAB*/ void mexFunction( int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { // Only remap cout if we aren't using octave since octave already does this. #if !defined(OCTAVE_IMPORT) && !defined(OCTAVE_API) // make it so cout prints to mexPrintf() static mex_binding::mex_streambuf sb; #endif mex_binding::call_mex_function(mex_function, nlhs, plhs, nrhs, prhs); } // ----------------------------------------------------------------------------------------