Commit ae69a11e authored by Davis King's avatar Davis King

Merged in code changes from MITIE project

parent 5cff6b95
cmake_minimum_required(VERSION 2.6.4)
# Don't add dlib if it's already been added to the cmake project
if (NOT TARGET dlib)
......
cmake_minimum_required(VERSION 2.8.4)
PROJECT(mex_functions)
include(cmake_mex_wrapper)
include(../cmake)
# Compile the example_mex_function.cpp file and link it to dlib. Note
# that you can give a list of things to link to here. E.g.
# add_mex_function(some_other_mex_function pthread dlib fftw)
add_mex_function(example_mex_function dlib)
add_mex_function(example_mex_callback dlib)
This folder contains a set of tools which make it easy to create MATLAB mex
functions. To understand how they work, you should read the
example_mex_function.cpp and example_mex_callback.cpp examples.
To compile them, you can use CMake. In particular, from this folder execute
these commands:
mkdir build
cd build
cmake ..
cmake --build . --config release --target install
That should build the mex files on any platform.
Note that on windows you will probably need to tell CMake to use a 64bit
version of visual studio. You can do this by using a command like:
cmake -G "Visual Studio 10 Win64" ..
instead of
cmake ..
// 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)
#ifndef MIT_LL_CALL_MATLAB_H__
#define MIT_LL_CALL_MATLAB_H__
#include <string>
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <typename T>
struct output_decorator
{
output_decorator(T& item_):item(item_){}
T& item;
};
template <typename T>
output_decorator<T> returns(T& item) { return output_decorator<T>(item); }
/*!
ensures
- decorates item as an output type. This stuff is used by the call_matlab()
functions to tell if an argument is an input to the function or is supposed
to be bound to one of the return arguments.
!*/
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
struct function_handle
{
/*!
WHAT THIS OBJECT REPRESENTS
This type is used to represent function handles passed from MATLAB into a
mex function. You can call the function referenced by the handle by
saying:
call_matlab(my_handle);
!*/
// These two lines are just implementation details, ignore them.
function_handle():h(0){}
void* const h;
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
void call_matlab (
const std::string& function_name
);
/*!
ensures
- Calls MATLAB's function of the given name
!*/
// ----------------------------------------------------------------------------------------
void call_matlab (
const function_handle& funct
);
/*!
ensures
- Calls MATLAB's function represented by the handle funct
!*/
// ----------------------------------------------------------------------------------------
template <
typename T1
>
void call_matlab (
const std::string& function_name,
const T1& A1
);
/*!
ensures
- calls MATLAB's function of the given name.
- if (A1 is not decorated as an output by returns()) then
- A1 is passed as an argument into the MATLAB function
- else
- A1 is treated as the first return value from the MATLAB function.
!*/
template <
typename T1
>
void call_matlab (
const function_handle& funct,
const T1& A1
) { call_matlab("feval", funct, A1); }
/*!
ensures
- Calls MATLAB's function represented by the handle funct
- if (A1 is not decorated as an output by returns()) then
- A1 is passed as an argument into the MATLAB function
- else
- A1 is treated as the first return value from the MATLAB function.
!*/
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
/*
The rest of this file is just overloads of call_matlab() for up to 10 arguments (or
just 9 arguments if function_handle is used). They all do the same thing as the above
version of call_matlab(). Generally, any argument not decorated by returns() is an
input to the MATLAB function. On the other hand, all arguments decorated by returns()
are treated as outputs.
*/
// ----------------------------------------------------------------------------------------
template <
typename T1,
typename T2
>
void call_matlab (
const std::string& function_name,
const T1& A1,
const T2& A2
);
// ----------------------------------------------------------------------------------------
template <
typename T1,
typename T2,
typename T3
>
void call_matlab (
const std::string& function_name,
const T1& A1,
const T2& A2,
const T3& A3
);
// ----------------------------------------------------------------------------------------
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
);
// ----------------------------------------------------------------------------------------
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
);
// ----------------------------------------------------------------------------------------
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
);
// ----------------------------------------------------------------------------------------
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
);
// ----------------------------------------------------------------------------------------
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
);
// ----------------------------------------------------------------------------------------
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
);
// ----------------------------------------------------------------------------------------
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
);
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename T1,
typename T2
>
void call_matlab (
const function_handle& funct,
const T1& A1,
const T2& A2
)
{
call_matlab("feval", funct, A1, A2);
}
template <
typename T1,
typename T2,
typename T3
>
void call_matlab (
const function_handle& funct,
const T1& A1,
const T2& A2,
const T3& A3
)
{
call_matlab("feval", funct, A1, A2, A3);
}
template <
typename T1,
typename T2,
typename T3,
typename T4
>
void call_matlab (
const function_handle& funct,
const T1& A1,
const T2& A2,
const T3& A3,
const T4& A4
)
{
call_matlab("feval", funct, A1, A2, A3, A4);
}
template <
typename T1,
typename T2,
typename T3,
typename T4,
typename T5
>
void call_matlab (
const function_handle& funct,
const T1& A1,
const T2& A2,
const T3& A3,
const T4& A4,
const T5& A5
)
{
call_matlab("feval", funct, A1, A2, A3, A4, A5);
}
template <
typename T1,
typename T2,
typename T3,
typename T4,
typename T5,
typename T6
>
void call_matlab (
const function_handle& funct,
const T1& A1,
const T2& A2,
const T3& A3,
const T4& A4,
const T5& A5,
const T6& A6
)
{
call_matlab("feval", funct, A1, A2, A3, A4, A5, A6);
}
template <
typename T1,
typename T2,
typename T3,
typename T4,
typename T5,
typename T6,
typename T7
>
void call_matlab (
const function_handle& funct,
const T1& A1,
const T2& A2,
const T3& A3,
const T4& A4,
const T5& A5,
const T6& A6,
const T7& A7
)
{
call_matlab("feval", funct, A1, A2, A3, A4, A5, A6, A7);
}
template <
typename T1,
typename T2,
typename T3,
typename T4,
typename T5,
typename T6,
typename T7,
typename T8
>
void call_matlab (
const function_handle& funct,
const T1& A1,
const T2& A2,
const T3& A3,
const T4& A4,
const T5& A5,
const T6& A6,
const T7& A7,
const T8& A8
)
{
call_matlab("feval", funct, A1, A2, A3, A4, A5, A6, A7, A8);
}
template <
typename T1,
typename T2,
typename T3,
typename T4,
typename T5,
typename T6,
typename T7,
typename T8,
typename T9
>
void call_matlab (
const function_handle& funct,
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
)
{
call_matlab("feval", funct, A1, A2, A3, A4, A5, A6, A7, A8, A9);
}
// ----------------------------------------------------------------------------------------
#endif // MIT_LL_CALL_MATLAB_H__
# This file figured out where MATLAB is and then defines a macro, add_mex_function(name)
# which when called instructs CMake to build a mex file from a file called name.cpp. Note
# that additional library dependencies can be added like this: add_mex_function(name lib1 dlib libetc).
# That is, just add more libraries after the name and they will be build into the mex file.
cmake_minimum_required(VERSION 2.8.4)
# Find MATLAB's include directory and needed libraries
find_program(MATLAB_EXECUTABLE matlab PATHS
"C:/Program Files/MATLAB/*/bin"
"C:/Program Files (x86)/MATLAB/*/bin"
)
# Resolve symbolic links to try and get the real path to the MATLAB executable
get_filename_component(MATLAB_EXECUTABLE ${MATLAB_EXECUTABLE} REALPATH)
# Now get MATLAB root directory
get_filename_component(MATLAB_HOME ${MATLAB_EXECUTABLE} PATH)
get_filename_component(MATLAB_HOME ${MATLAB_HOME} PATH)
set(MATLAB_LIB_FOLDERS
"${MATLAB_HOME}/extern/lib/win64/microsoft"
"${MATLAB_HOME}/bin/glnxa64"
)
# Find the MATLAB libraries that need to get linked into the mex file
if (WIN32)
find_library(MATLAB_MEX_LIBRARY libmex PATHS ${MATLAB_LIB_FOLDERS} )
find_library(MATLAB_MX_LIBRARY libmx PATHS ${MATLAB_LIB_FOLDERS} )
find_library(MATLAB_ENG_LIBRARY libeng PATHS ${MATLAB_LIB_FOLDERS} )
else()
find_library(MATLAB_MEX_LIBRARY mex PATHS ${MATLAB_LIB_FOLDERS} )
find_library(MATLAB_MX_LIBRARY mx PATHS ${MATLAB_LIB_FOLDERS} )
find_library(MATLAB_ENG_LIBRARY eng PATHS ${MATLAB_LIB_FOLDERS} )
endif()
set(MATLAB_LIBRARIES ${MATLAB_MEX_LIBRARY} ${MATLAB_MX_LIBRARY} ${MATLAB_ENG_LIBRARY})
INCLUDE_DIRECTORIES("${MATLAB_HOME}/extern/include")
# Determine the path to cmake_mex_wrapper file so we can add it to the include search path..
string(REGEX REPLACE "cmake_mex_wrapper$" "" dlib_matlab_binding_path ${CMAKE_CURRENT_LIST_FILE})
INCLUDE_DIRECTORIES("${dlib_matlab_binding_path}")
# Determine the path to dlib so we can add it to the include search path.
string(REGEX REPLACE "cmake_mex_wrapper$" "" dlib_path ${CMAKE_CURRENT_LIST_FILE})
INCLUDE_DIRECTORIES(${dlib_path}/../..)
ADD_DEFINITIONS(-DMATLAB_MEX_FILE)
# Determine the path to our CMakeLists.txt file. This is the file that
# includeded the one you are reading right now. So here we make it so that
# when you run the install target it will copy the compiled mex files into the
# same folder as the parent CMakeLists.txt file.
string(REGEX REPLACE "CMakeLists.txt$" "" install_dir ${CMAKE_PARENT_LIST_FILE})
set(CMAKE_INSTALL_PREFIX "${install_dir}")
set(CMAKE_INSTALL_SYSTEM_RUNTIME_DESTINATION "${install_dir}")
INCLUDE(InstallRequiredSystemLibraries)
MACRO(add_mex_function name )
ADD_LIBRARY(${name} MODULE ${name}.cpp )
# Change the output file extension to a mex extension.
if (WIN32)
set_target_properties(${name} PROPERTIES SUFFIX ".mexw64")
elseif(APPLE)
set_target_properties(${name} PROPERTIES SUFFIX ".mexmaci64")
else()
set_target_properties(${name} PROPERTIES SUFFIX ".mexa64")
endif()
set_target_properties(${name} PROPERTIES PREFIX "")
TARGET_LINK_LIBRARIES(${name} ${MATLAB_LIBRARIES} ${ARGN})
install(TARGETS ${name} DESTINATION "${install_dir}")
ENDMACRO()
% This example calls the two mex functions defined in this folder. As you
% can see, you call them just like you would normal MATLAB functions.
x = magic(3)
y = 2*magic(3)
[out1, out2] = example_mex_function(x,y, 12345)
z = example_mex_callback(x, @(a)a+a)
#include "call_matlab.h"
#include "dlib/matrix.h"
using namespace dlib;
using namespace std;
/*
This mex function takes a MATLAB function handle, calls it, and
returns the results.
For example, you can call this function in MATLAB like so:
A = magic(3)
y = example_mex_callback(A, @(x)x+x)
This will result in y containing the value 2*A.
*/
void mex_function (
const matrix<double>& A,
const function_handle& f,
matrix<double>& result
)
{
// The f argument to this function is a function handle passed from MATLAB. To
// call it we use the following syntax:
call_matlab(f, A, returns(result));
// This is equivalent to result = f(A). Therefore, the returns(variable) syntax
// is used to indicate which variables are outputs of the function.
// Another thing we can do is call MATLAB functions based on their string name
// rather than a function_handle. Here is an example of calling eigs().
matrix<double> m(2,2);
m = 1,2,
3,4;
matrix<double> v,d;
// This is equivalent to [v,d] = eigs(m);
call_matlab("eigs", m, returns(v), returns(d));
cout << "eigenvectors: \n" << v << endl;
cout << "eigenvalues: \n" << d << endl;
}
// #including this brings in all the mex boiler plate needed by MATLAB.
#include "mex_wrapper.cpp"
#include "dlib/matrix.h"
using namespace dlib;
using namespace std;
/*!
This file defines a function callable from MATLAB once you mex it.
It computes the same thing as the following MATLAB function:
function [A, B] = example_mex_function(x, y, some_number)
A = x+y;
B = sum(sum(x+y));
disp(['some_number: ' num2str(some_number)])
end
VALID INPUT AND OUTPUT ARGUMENTS
The mex wrapper can handle the following kinds of input and output arguments:
- Types corresponding to a MATLAB matrix
- a dlib::matrix containing any kind of scalar value.
- a dlib::array2d containing any kind of scalar value.
- a dlib::vector containing any kind of scalar value.
- a dlib::point
- RGB color images
- dlib::array2d<dlib::rgb_pixel> can be used to represent
MATLAB uint8 MxNx3 images.
- Types corresponding to a MATLAB scalar
- any kind of scalar value, e.g. double, int, etc.
- Types corresponding to a MATLAB string
- std::string
- Types corresponding to a MATLAB cell array
- a std::vector or dlib::array containing any of the above
types of objects or std::vector or dlib::array objects.
!*/
// You can also define default values for your input arguments. So
// here we say that if the user in MATLAB doesn't provide the "some_number"
// then it will get a value of 3.141.
#define ARG_5_DEFAULT 3.141
// Make a function named mex_function() and put your code inside it.
// Note that the return type should be void. Use non-const reference
// arguments to return outputs. Finally, mex_function() must have no
// more than 10 arguments.
void mex_function (
const matrix<double>& x,
const matrix<double>& y,
matrix<double>& out1,
double& out2,
double some_number
)
{
out1 = x + y;
out2 = sum(x+y);
// we can also use cout to print things as usual:
cout << "some_number: "<< some_number << endl;
}
// #including this brings in all the mex boiler plate needed by MATLAB.
#include "mex_wrapper.cpp"
/*
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 <sstream>
#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 <typename T>
struct is_input_type
{
const static unsigned long value = (!is_same_type<void,T>::value && (!is_reference_type<T>::value || is_const_type<T>::value )) ? 1 : 0;
};
template <typename T>
struct is_output_type
{
const static unsigned long value = (!is_same_type<void,T>::value && is_reference_type<T>::value && !is_const_type<T>::value) ? 1 : 0;
};
template <typename funct>
struct funct_traits
{
const static unsigned long num_inputs = is_input_type<typename sig_traits<funct>::arg1_type>::value +
is_input_type<typename sig_traits<funct>::arg2_type>::value +
is_input_type<typename sig_traits<funct>::arg3_type>::value +
is_input_type<typename sig_traits<funct>::arg4_type>::value +
is_input_type<typename sig_traits<funct>::arg5_type>::value +
is_input_type<typename sig_traits<funct>::arg6_type>::value +
is_input_type<typename sig_traits<funct>::arg7_type>::value +
is_input_type<typename sig_traits<funct>::arg8_type>::value +
is_input_type<typename sig_traits<funct>::arg9_type>::value +
is_input_type<typename sig_traits<funct>::arg10_type>::value;
const static unsigned long num_outputs= is_output_type<typename sig_traits<funct>::arg1_type>::value +
is_output_type<typename sig_traits<funct>::arg2_type>::value +
is_output_type<typename sig_traits<funct>::arg3_type>::value +
is_output_type<typename sig_traits<funct>::arg4_type>::value +
is_output_type<typename sig_traits<funct>::arg5_type>::value +
is_output_type<typename sig_traits<funct>::arg6_type>::value +
is_output_type<typename sig_traits<funct>::arg7_type>::value +
is_output_type<typename sig_traits<funct>::arg8_type>::value +
is_output_type<typename sig_traits<funct>::arg9_type>::value +
is_output_type<typename sig_traits<funct>::arg10_type>::value;
};
// ----------------------------------------------------------------------------------------
template <typename T>
struct is_array_type
{
// true if T is std::vector or dlib::array
const static bool value = is_std_vector<T>::value || dlib::is_array<T>::value;
};
// ----------------------------------------------------------------------------------------
template <
typename T,
typename enabled = void
>
struct inner_type
{
typedef T type;
};
template < typename T>
struct inner_type<T, typename dlib::enable_if_c<is_matrix<T>::value || is_array2d<T>::value || dlib::is_array<T>::value >::type>
{
typedef typename T::type type;
};
template < typename T>
struct inner_type<T, typename dlib::enable_if<is_std_vector<T> >::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<is_matrix<matrix_type>::value && is_same_type<typename inner_type<matrix_type>::type,typename EXP::type>::value >::type
assign_mat (
const long arg_idx,
matrix_type& m,
const matrix_exp<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<is_array2d<matrix_type>::value && is_same_type<typename inner_type<matrix_type>::type,typename EXP::type>::value >::type
assign_mat (
const long arg_idx,
matrix_type& m,
const matrix_exp<EXP>& src
)
{
assign_image(m , trans(src));
}
template <
typename matrix_type,
typename EXP
>
typename disable_if_c<(is_array2d<matrix_type>::value || is_matrix<matrix_type>::value) &&
is_same_type<typename inner_type<matrix_type>::type,typename EXP::type>::value >::type
assign_mat (
const long arg_idx,
matrix_type& ,
const matrix_exp<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<is_built_in_scalar_type<T>::value || is_same_type<T,bool>::value >::type
assign_scalar (
const long arg_idx,
T& dest,
const U& src
)
{
if (is_signed_type<U>::value && src < 0 && is_unsigned_type<T>::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<is_built_in_scalar_type<T>::value || is_same_type<T,bool>::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<void*&>(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<is_array_type<T> >::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<T>::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<is_array_type<T> >::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 <typename T>
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 <typename MM>
void assign_image(
const long ,
array2d<dlib::rgb_pixel,MM>& 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 <typename T>
void validate_and_populate_arg (
long arg_idx,
const mxArray *prhs,
T& arg
)
{
using namespace mex_binding;
if (is_built_in_scalar_type<T>::value || is_same_type<T,bool>::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<T>::value || is_array2d<T>::value)
{
typedef typename inner_type<T>::type type;
const int num_dims = mxGetNumberOfDimensions(prhs);
const long nr = mxGetM(prhs);
const long nc = mxGetN(prhs);
if (is_same_type<type,dlib::rgb_pixel>::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<type,double>::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<type, float>::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<type, bool>::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<type, dlib::uint8>::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<type, dlib::int8>::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<type, dlib::int16>::value ||
(is_same_type<type, short>::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<type, dlib::uint16>::value ||
(is_same_type<type, unsigned short>::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<type, dlib::int32>::value ||
(is_same_type<type, int>::value && sizeof(int) == sizeof(dlib::int32)) ||
(is_same_type<type, long>::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<type, dlib::uint32>::value ||
(is_same_type<type, unsigned int>::value && sizeof(unsigned int) == sizeof(dlib::uint32)) ||
(is_same_type<type, unsigned long>::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<type, dlib::uint64>::value ||
(is_same_type<type, unsigned int>::value && sizeof(unsigned int) == sizeof(dlib::uint64)) ||
(is_same_type<type, unsigned long>::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<type, dlib::int64>::value ||
(is_same_type<type, int>::value && sizeof(int) == sizeof(dlib::int64)) ||
(is_same_type<type, long>::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<T>::value)
{
assign_std_vector(arg_idx, arg, prhs);
}
else if (is_same_type<T,function_handle>::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 EXP>
typename dlib::enable_if<is_same_type<dlib::rgb_pixel,typename EXP::type> >::type assign_image_to_matlab (
dlib::uint8* mat,
const matrix_exp<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 T, typename EXP>
typename disable_if<is_same_type<dlib::rgb_pixel,typename EXP::type> >::type assign_image_to_matlab (
T* mat,
const matrix_exp<EXP>&
)
{
mexErrMsgIdAndTxt("mex_function:validate_and_populate_arg",
"mex_function uses unsupported output image argument type");
}
template <typename T>
typename dlib::enable_if<is_matrix<T> >::type assign_to_matlab(
mxArray*& plhs,
const T& item
)
{
typedef typename T::type type;
type* mat = 0;
if (is_same_type<double, type>::value)
{
plhs = mxCreateDoubleMatrix(item.nr(),
item.nc(),
mxREAL);
mat = (type*)mxGetPr(plhs);
}
else if (is_same_type<float, type>::value )
{
plhs = mxCreateNumericMatrix(item.nr(),
item.nc(),
mxSINGLE_CLASS,
mxREAL);
mat = (type*)mxGetData(plhs);
}
else if (is_same_type<bool, type>::value )
{
plhs = mxCreateLogicalMatrix(item.nr(),
item.nc());
mat = (type*)mxGetData(plhs);
}
else if (is_same_type<dlib::uint8, type>::value )
{
plhs = mxCreateNumericMatrix(item.nr(),
item.nc(),
mxUINT8_CLASS,
mxREAL);
mat = (type*)mxGetData(plhs);
}
else if (is_same_type<dlib::int8, type>::value )
{
plhs = mxCreateNumericMatrix(item.nr(),
item.nc(),
mxINT8_CLASS,
mxREAL);
mat = (type*)mxGetData(plhs);
}
else if (is_same_type<dlib::int16, type>::value ||
(is_same_type<short,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<dlib::uint16, type>::value ||
(is_same_type<unsigned short,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<dlib::int32, type>::value ||
(is_same_type<long,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<dlib::uint32, type>::value ||
(is_same_type<unsigned long,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<dlib::uint64, type>::value ||
(is_same_type<unsigned long,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<dlib::int64, type>::value ||
(is_same_type<long,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<dlib::rgb_pixel, 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 <typename T, typename MM>
void assign_to_matlab(
mxArray*& plhs,
const array2d<T,MM>& item
)
{
assign_to_matlab(plhs,array_to_matrix(item));
}
template <typename T>
typename dlib::enable_if<is_array_type<T> >::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 T>
typename dlib::disable_if_c<is_matrix<T>::value || is_array_type<T>::value ||
is_same_type<T,function_handle>::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 <typename funct>
void callit(
const funct& ,
int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[]
) const
{
typedef typename sig_traits<funct>::arg1_type arg1_type;
typename basic_type<arg1_type>::type A1;
int i = 0;
if (i < nrhs && is_input_type<arg1_type>::value) {validate_and_populate_arg(i,prhs[i],A1); ++i;} ELSE_ASSIGN_ARG_1;
mex_function(A1);
i = 0;
if (is_output_type<arg1_type>::value) {assign_to_matlab(plhs[i],A1); ++i;}
}
};
template <>
struct call_mex_function_helper<2>
{
template <typename funct>
void callit(
const funct& ,
int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[]
) const
{
typedef typename sig_traits<funct>::arg1_type arg1_type;
typedef typename sig_traits<funct>::arg2_type arg2_type;
typename basic_type<arg1_type>::type A1;
typename basic_type<arg2_type>::type A2;
int i = 0;
if (i < nrhs && is_input_type<arg1_type>::value) {validate_and_populate_arg(i,prhs[i],A1); ++i;} ELSE_ASSIGN_ARG_1;
if (i < nrhs && is_input_type<arg2_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<arg1_type>::value) {assign_to_matlab(plhs[i],A1); ++i;}
if (is_output_type<arg2_type>::value) {assign_to_matlab(plhs[i],A2); ++i;}
}
};
template <>
struct call_mex_function_helper<3>
{
template <typename funct>
void callit(
const funct& ,
int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[]
) const
{
typedef typename sig_traits<funct>::arg1_type arg1_type;
typedef typename sig_traits<funct>::arg2_type arg2_type;
typedef typename sig_traits<funct>::arg3_type arg3_type;
typename basic_type<arg1_type>::type A1;
typename basic_type<arg2_type>::type A2;
typename basic_type<arg3_type>::type A3;
int i = 0;
if (i < nrhs && is_input_type<arg1_type>::value) {validate_and_populate_arg(i,prhs[i],A1); ++i;} ELSE_ASSIGN_ARG_1;
if (i < nrhs && is_input_type<arg2_type>::value) {validate_and_populate_arg(i,prhs[i],A2); ++i;} ELSE_ASSIGN_ARG_2;
if (i < nrhs && is_input_type<arg3_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<arg1_type>::value) {assign_to_matlab(plhs[i],A1); ++i;}
if (is_output_type<arg2_type>::value) {assign_to_matlab(plhs[i],A2); ++i;}
if (is_output_type<arg3_type>::value) {assign_to_matlab(plhs[i],A3); ++i;}
}
};
template <>
struct call_mex_function_helper<4>
{
template <typename funct>
void callit(
const funct& ,
int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[]
) const
{
typedef typename sig_traits<funct>::arg1_type arg1_type;
typedef typename sig_traits<funct>::arg2_type arg2_type;
typedef typename sig_traits<funct>::arg3_type arg3_type;
typedef typename sig_traits<funct>::arg4_type arg4_type;
typename basic_type<arg1_type>::type A1;
typename basic_type<arg2_type>::type A2;
typename basic_type<arg3_type>::type A3;
typename basic_type<arg4_type>::type A4;
int i = 0;
if (i < nrhs && is_input_type<arg1_type>::value) {validate_and_populate_arg(i,prhs[i],A1); ++i;} ELSE_ASSIGN_ARG_1;
if (i < nrhs && is_input_type<arg2_type>::value) {validate_and_populate_arg(i,prhs[i],A2); ++i;} ELSE_ASSIGN_ARG_2;
if (i < nrhs && is_input_type<arg3_type>::value) {validate_and_populate_arg(i,prhs[i],A3); ++i;} ELSE_ASSIGN_ARG_3;
if (i < nrhs && is_input_type<arg4_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<arg1_type>::value) {assign_to_matlab(plhs[i],A1); ++i;}
if (is_output_type<arg2_type>::value) {assign_to_matlab(plhs[i],A2); ++i;}
if (is_output_type<arg3_type>::value) {assign_to_matlab(plhs[i],A3); ++i;}
if (is_output_type<arg4_type>::value) {assign_to_matlab(plhs[i],A4); ++i;}
}
};
template <>
struct call_mex_function_helper<5>
{
template <typename funct>
void callit(
const funct& ,
int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[]
) const
{
typedef typename sig_traits<funct>::arg1_type arg1_type;
typedef typename sig_traits<funct>::arg2_type arg2_type;
typedef typename sig_traits<funct>::arg3_type arg3_type;
typedef typename sig_traits<funct>::arg4_type arg4_type;
typedef typename sig_traits<funct>::arg5_type arg5_type;
typename basic_type<arg1_type>::type A1;
typename basic_type<arg2_type>::type A2;
typename basic_type<arg3_type>::type A3;
typename basic_type<arg4_type>::type A4;
typename basic_type<arg5_type>::type A5;
int i = 0;
if (i < nrhs && is_input_type<arg1_type>::value) {validate_and_populate_arg(i,prhs[i],A1); ++i;} ELSE_ASSIGN_ARG_1;
if (i < nrhs && is_input_type<arg2_type>::value) {validate_and_populate_arg(i,prhs[i],A2); ++i;} ELSE_ASSIGN_ARG_2;
if (i < nrhs && is_input_type<arg3_type>::value) {validate_and_populate_arg(i,prhs[i],A3); ++i;} ELSE_ASSIGN_ARG_3;
if (i < nrhs && is_input_type<arg4_type>::value) {validate_and_populate_arg(i,prhs[i],A4); ++i;} ELSE_ASSIGN_ARG_4;
if (i < nrhs && is_input_type<arg5_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<arg1_type>::value) {assign_to_matlab(plhs[i],A1); ++i;}
if (is_output_type<arg2_type>::value) {assign_to_matlab(plhs[i],A2); ++i;}
if (is_output_type<arg3_type>::value) {assign_to_matlab(plhs[i],A3); ++i;}
if (is_output_type<arg4_type>::value) {assign_to_matlab(plhs[i],A4); ++i;}
if (is_output_type<arg5_type>::value) {assign_to_matlab(plhs[i],A5); ++i;}
}
};
template <>
struct call_mex_function_helper<6>
{
template <typename funct>
void callit(
const funct& ,
int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[]
) const
{
typedef typename sig_traits<funct>::arg1_type arg1_type;
typedef typename sig_traits<funct>::arg2_type arg2_type;
typedef typename sig_traits<funct>::arg3_type arg3_type;
typedef typename sig_traits<funct>::arg4_type arg4_type;
typedef typename sig_traits<funct>::arg5_type arg5_type;
typedef typename sig_traits<funct>::arg6_type arg6_type;
typename basic_type<arg1_type>::type A1;
typename basic_type<arg2_type>::type A2;
typename basic_type<arg3_type>::type A3;
typename basic_type<arg4_type>::type A4;
typename basic_type<arg5_type>::type A5;
typename basic_type<arg6_type>::type A6;
int i = 0;
if (i < nrhs && is_input_type<arg1_type>::value) {validate_and_populate_arg(i,prhs[i],A1); ++i;} ELSE_ASSIGN_ARG_1;
if (i < nrhs && is_input_type<arg2_type>::value) {validate_and_populate_arg(i,prhs[i],A2); ++i;} ELSE_ASSIGN_ARG_2;
if (i < nrhs && is_input_type<arg3_type>::value) {validate_and_populate_arg(i,prhs[i],A3); ++i;} ELSE_ASSIGN_ARG_3;
if (i < nrhs && is_input_type<arg4_type>::value) {validate_and_populate_arg(i,prhs[i],A4); ++i;} ELSE_ASSIGN_ARG_4;
if (i < nrhs && is_input_type<arg5_type>::value) {validate_and_populate_arg(i,prhs[i],A5); ++i;} ELSE_ASSIGN_ARG_5;
if (i < nrhs && is_input_type<arg6_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<arg1_type>::value) {assign_to_matlab(plhs[i],A1); ++i;}
if (is_output_type<arg2_type>::value) {assign_to_matlab(plhs[i],A2); ++i;}
if (is_output_type<arg3_type>::value) {assign_to_matlab(plhs[i],A3); ++i;}
if (is_output_type<arg4_type>::value) {assign_to_matlab(plhs[i],A4); ++i;}
if (is_output_type<arg5_type>::value) {assign_to_matlab(plhs[i],A5); ++i;}
if (is_output_type<arg6_type>::value) {assign_to_matlab(plhs[i],A6); ++i;}
}
};
template <>
struct call_mex_function_helper<7>
{
template <typename funct>
void callit(
const funct& ,
int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[]
) const
{
typedef typename sig_traits<funct>::arg1_type arg1_type;
typedef typename sig_traits<funct>::arg2_type arg2_type;
typedef typename sig_traits<funct>::arg3_type arg3_type;
typedef typename sig_traits<funct>::arg4_type arg4_type;
typedef typename sig_traits<funct>::arg5_type arg5_type;
typedef typename sig_traits<funct>::arg6_type arg6_type;
typedef typename sig_traits<funct>::arg7_type arg7_type;
typename basic_type<arg1_type>::type A1;
typename basic_type<arg2_type>::type A2;
typename basic_type<arg3_type>::type A3;
typename basic_type<arg4_type>::type A4;
typename basic_type<arg5_type>::type A5;
typename basic_type<arg6_type>::type A6;
typename basic_type<arg7_type>::type A7;
int i = 0;
if (i < nrhs && is_input_type<arg1_type>::value) {validate_and_populate_arg(i,prhs[i],A1); ++i;} ELSE_ASSIGN_ARG_1;
if (i < nrhs && is_input_type<arg2_type>::value) {validate_and_populate_arg(i,prhs[i],A2); ++i;} ELSE_ASSIGN_ARG_2;
if (i < nrhs && is_input_type<arg3_type>::value) {validate_and_populate_arg(i,prhs[i],A3); ++i;} ELSE_ASSIGN_ARG_3;
if (i < nrhs && is_input_type<arg4_type>::value) {validate_and_populate_arg(i,prhs[i],A4); ++i;} ELSE_ASSIGN_ARG_4;
if (i < nrhs && is_input_type<arg5_type>::value) {validate_and_populate_arg(i,prhs[i],A5); ++i;} ELSE_ASSIGN_ARG_5;
if (i < nrhs && is_input_type<arg6_type>::value) {validate_and_populate_arg(i,prhs[i],A6); ++i;} ELSE_ASSIGN_ARG_6;
if (i < nrhs && is_input_type<arg7_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<arg1_type>::value) {assign_to_matlab(plhs[i],A1); ++i;}
if (is_output_type<arg2_type>::value) {assign_to_matlab(plhs[i],A2); ++i;}
if (is_output_type<arg3_type>::value) {assign_to_matlab(plhs[i],A3); ++i;}
if (is_output_type<arg4_type>::value) {assign_to_matlab(plhs[i],A4); ++i;}
if (is_output_type<arg5_type>::value) {assign_to_matlab(plhs[i],A5); ++i;}
if (is_output_type<arg6_type>::value) {assign_to_matlab(plhs[i],A6); ++i;}
if (is_output_type<arg7_type>::value) {assign_to_matlab(plhs[i],A7); ++i;}
}
};
template <>
struct call_mex_function_helper<8>
{
template <typename funct>
void callit(
const funct& ,
int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[]
) const
{
typedef typename sig_traits<funct>::arg1_type arg1_type;
typedef typename sig_traits<funct>::arg2_type arg2_type;
typedef typename sig_traits<funct>::arg3_type arg3_type;
typedef typename sig_traits<funct>::arg4_type arg4_type;
typedef typename sig_traits<funct>::arg5_type arg5_type;
typedef typename sig_traits<funct>::arg6_type arg6_type;
typedef typename sig_traits<funct>::arg7_type arg7_type;
typedef typename sig_traits<funct>::arg8_type arg8_type;
typename basic_type<arg1_type>::type A1;
typename basic_type<arg2_type>::type A2;
typename basic_type<arg3_type>::type A3;
typename basic_type<arg4_type>::type A4;
typename basic_type<arg5_type>::type A5;
typename basic_type<arg6_type>::type A6;
typename basic_type<arg7_type>::type A7;
typename basic_type<arg8_type>::type A8;
int i = 0;
if (i < nrhs && is_input_type<arg1_type>::value) {validate_and_populate_arg(i,prhs[i],A1); ++i;} ELSE_ASSIGN_ARG_1;
if (i < nrhs && is_input_type<arg2_type>::value) {validate_and_populate_arg(i,prhs[i],A2); ++i;} ELSE_ASSIGN_ARG_2;
if (i < nrhs && is_input_type<arg3_type>::value) {validate_and_populate_arg(i,prhs[i],A3); ++i;} ELSE_ASSIGN_ARG_3;
if (i < nrhs && is_input_type<arg4_type>::value) {validate_and_populate_arg(i,prhs[i],A4); ++i;} ELSE_ASSIGN_ARG_4;
if (i < nrhs && is_input_type<arg5_type>::value) {validate_and_populate_arg(i,prhs[i],A5); ++i;} ELSE_ASSIGN_ARG_5;
if (i < nrhs && is_input_type<arg6_type>::value) {validate_and_populate_arg(i,prhs[i],A6); ++i;} ELSE_ASSIGN_ARG_6;
if (i < nrhs && is_input_type<arg7_type>::value) {validate_and_populate_arg(i,prhs[i],A7); ++i;} ELSE_ASSIGN_ARG_7;
if (i < nrhs && is_input_type<arg8_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<arg1_type>::value) {assign_to_matlab(plhs[i],A1); ++i;}
if (is_output_type<arg2_type>::value) {assign_to_matlab(plhs[i],A2); ++i;}
if (is_output_type<arg3_type>::value) {assign_to_matlab(plhs[i],A3); ++i;}
if (is_output_type<arg4_type>::value) {assign_to_matlab(plhs[i],A4); ++i;}
if (is_output_type<arg5_type>::value) {assign_to_matlab(plhs[i],A5); ++i;}
if (is_output_type<arg6_type>::value) {assign_to_matlab(plhs[i],A6); ++i;}
if (is_output_type<arg7_type>::value) {assign_to_matlab(plhs[i],A7); ++i;}
if (is_output_type<arg8_type>::value) {assign_to_matlab(plhs[i],A8); ++i;}
}
};
template <>
struct call_mex_function_helper<9>
{
template <typename funct>
void callit(
const funct& ,
int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[]
) const
{
typedef typename sig_traits<funct>::arg1_type arg1_type;
typedef typename sig_traits<funct>::arg2_type arg2_type;
typedef typename sig_traits<funct>::arg3_type arg3_type;
typedef typename sig_traits<funct>::arg4_type arg4_type;
typedef typename sig_traits<funct>::arg5_type arg5_type;
typedef typename sig_traits<funct>::arg6_type arg6_type;
typedef typename sig_traits<funct>::arg7_type arg7_type;
typedef typename sig_traits<funct>::arg8_type arg8_type;
typedef typename sig_traits<funct>::arg9_type arg9_type;
typename basic_type<arg1_type>::type A1;
typename basic_type<arg2_type>::type A2;
typename basic_type<arg3_type>::type A3;
typename basic_type<arg4_type>::type A4;
typename basic_type<arg5_type>::type A5;
typename basic_type<arg6_type>::type A6;
typename basic_type<arg7_type>::type A7;
typename basic_type<arg8_type>::type A8;
typename basic_type<arg9_type>::type A9;
int i = 0;
if (i < nrhs && is_input_type<arg1_type>::value) {validate_and_populate_arg(i,prhs[i],A1); ++i;} ELSE_ASSIGN_ARG_1;
if (i < nrhs && is_input_type<arg2_type>::value) {validate_and_populate_arg(i,prhs[i],A2); ++i;} ELSE_ASSIGN_ARG_2;
if (i < nrhs && is_input_type<arg3_type>::value) {validate_and_populate_arg(i,prhs[i],A3); ++i;} ELSE_ASSIGN_ARG_3;
if (i < nrhs && is_input_type<arg4_type>::value) {validate_and_populate_arg(i,prhs[i],A4); ++i;} ELSE_ASSIGN_ARG_4;
if (i < nrhs && is_input_type<arg5_type>::value) {validate_and_populate_arg(i,prhs[i],A5); ++i;} ELSE_ASSIGN_ARG_5;
if (i < nrhs && is_input_type<arg6_type>::value) {validate_and_populate_arg(i,prhs[i],A6); ++i;} ELSE_ASSIGN_ARG_6;
if (i < nrhs && is_input_type<arg7_type>::value) {validate_and_populate_arg(i,prhs[i],A7); ++i;} ELSE_ASSIGN_ARG_7;
if (i < nrhs && is_input_type<arg8_type>::value) {validate_and_populate_arg(i,prhs[i],A8); ++i;} ELSE_ASSIGN_ARG_8;
if (i < nrhs && is_input_type<arg9_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<arg1_type>::value) {assign_to_matlab(plhs[i],A1); ++i;}
if (is_output_type<arg2_type>::value) {assign_to_matlab(plhs[i],A2); ++i;}
if (is_output_type<arg3_type>::value) {assign_to_matlab(plhs[i],A3); ++i;}
if (is_output_type<arg4_type>::value) {assign_to_matlab(plhs[i],A4); ++i;}
if (is_output_type<arg5_type>::value) {assign_to_matlab(plhs[i],A5); ++i;}
if (is_output_type<arg6_type>::value) {assign_to_matlab(plhs[i],A6); ++i;}
if (is_output_type<arg7_type>::value) {assign_to_matlab(plhs[i],A7); ++i;}
if (is_output_type<arg8_type>::value) {assign_to_matlab(plhs[i],A8); ++i;}
if (is_output_type<arg9_type>::value) {assign_to_matlab(plhs[i],A9); ++i;}
}
};
template <>
struct call_mex_function_helper<10>
{
template <typename funct>
void callit(
const funct& ,
int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[]
) const
{
typedef typename sig_traits<funct>::arg1_type arg1_type;
typedef typename sig_traits<funct>::arg2_type arg2_type;
typedef typename sig_traits<funct>::arg3_type arg3_type;
typedef typename sig_traits<funct>::arg4_type arg4_type;
typedef typename sig_traits<funct>::arg5_type arg5_type;
typedef typename sig_traits<funct>::arg6_type arg6_type;
typedef typename sig_traits<funct>::arg7_type arg7_type;
typedef typename sig_traits<funct>::arg8_type arg8_type;
typedef typename sig_traits<funct>::arg9_type arg9_type;
typedef typename sig_traits<funct>::arg10_type arg10_type;
typename basic_type<arg1_type>::type A1;
typename basic_type<arg2_type>::type A2;
typename basic_type<arg3_type>::type A3;
typename basic_type<arg4_type>::type A4;
typename basic_type<arg5_type>::type A5;
typename basic_type<arg6_type>::type A6;
typename basic_type<arg7_type>::type A7;
typename basic_type<arg8_type>::type A8;
typename basic_type<arg9_type>::type A9;
typename basic_type<arg10_type>::type A10;
int i = 0;
if (i < nrhs && is_input_type<arg1_type>::value) {validate_and_populate_arg(i,prhs[i],A1); ++i;} ELSE_ASSIGN_ARG_1;
if (i < nrhs && is_input_type<arg2_type>::value) {validate_and_populate_arg(i,prhs[i],A2); ++i;} ELSE_ASSIGN_ARG_2;
if (i < nrhs && is_input_type<arg3_type>::value) {validate_and_populate_arg(i,prhs[i],A3); ++i;} ELSE_ASSIGN_ARG_3;
if (i < nrhs && is_input_type<arg4_type>::value) {validate_and_populate_arg(i,prhs[i],A4); ++i;} ELSE_ASSIGN_ARG_4;
if (i < nrhs && is_input_type<arg5_type>::value) {validate_and_populate_arg(i,prhs[i],A5); ++i;} ELSE_ASSIGN_ARG_5;
if (i < nrhs && is_input_type<arg6_type>::value) {validate_and_populate_arg(i,prhs[i],A6); ++i;} ELSE_ASSIGN_ARG_6;
if (i < nrhs && is_input_type<arg7_type>::value) {validate_and_populate_arg(i,prhs[i],A7); ++i;} ELSE_ASSIGN_ARG_7;
if (i < nrhs && is_input_type<arg8_type>::value) {validate_and_populate_arg(i,prhs[i],A8); ++i;} ELSE_ASSIGN_ARG_8;
if (i < nrhs && is_input_type<arg9_type>::value) {validate_and_populate_arg(i,prhs[i],A9); ++i;} ELSE_ASSIGN_ARG_9;
if (i < nrhs && is_input_type<arg10_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<arg1_type>::value) {assign_to_matlab(plhs[i],A1); ++i;}
if (is_output_type<arg2_type>::value) {assign_to_matlab(plhs[i],A2); ++i;}
if (is_output_type<arg3_type>::value) {assign_to_matlab(plhs[i],A3); ++i;}
if (is_output_type<arg4_type>::value) {assign_to_matlab(plhs[i],A4); ++i;}
if (is_output_type<arg5_type>::value) {assign_to_matlab(plhs[i],A5); ++i;}
if (is_output_type<arg6_type>::value) {assign_to_matlab(plhs[i],A6); ++i;}
if (is_output_type<arg7_type>::value) {assign_to_matlab(plhs[i],A7); ++i;}
if (is_output_type<arg8_type>::value) {assign_to_matlab(plhs[i],A8); ++i;}
if (is_output_type<arg9_type>::value) {assign_to_matlab(plhs[i],A9); ++i;}
if (is_output_type<arg10_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<funct>::num_inputs;
const long expected_nlhs = funct_traits<funct>::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<typename sig_traits<funct>::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<typename sig_traits<funct>::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<typename sig_traits<funct>::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<typename sig_traits<funct>::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<typename sig_traits<funct>::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<typename sig_traits<funct>::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<typename sig_traits<funct>::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<typename sig_traits<funct>::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<typename sig_traits<funct>::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<typename sig_traits<funct>::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<sig_traits<funct>::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<int>(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<char> buf;
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <typename T>
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<mxArray*>(item.h);
++nrhs;
}
template <typename T>
void setup_input_args (
mxArray*& array,
const output_decorator<T>& item,
int& nrhs
)
{
}
template <typename T>
void setup_output_args (
const std::string& function_name,
mxArray* array,
const T& item,
int& nrhs
)
{
}
template <typename T>
void setup_output_args (
const std::string& function_name,
mxArray* array,
const output_decorator<T>& item,
int& i
)
{
try
{
validate_and_populate_arg(i,array,const_cast<T&>(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 <typename T1>
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<T1,function_handle>::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<T1>(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<T1>(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<T1>(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<T1>(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<T1>(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<T1>(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<T1>(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<T1>(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<T1>(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<T1>(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);
}
// ----------------------------------------------------------------------------------------
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment