Commit 032a8bf6 authored by Davis King's avatar Davis King

merged

parents d8a23c87 7ca1fb16
...@@ -13,4 +13,5 @@ include(../cmake) ...@@ -13,4 +13,5 @@ include(../cmake)
add_mex_function(example_mex_function dlib) add_mex_function(example_mex_function dlib)
add_mex_function(example_mex_callback dlib) add_mex_function(example_mex_callback dlib)
add_mex_function(example_mex_struct dlib) add_mex_function(example_mex_struct dlib)
add_mex_function(mex_example_class dlib)
// The contents of this file are in the public domain. See LICENSE_FOR_EXAMPLE_PROGRAMS.txt
/*
This mex file will create a MATLAB function called mex_example_class. If you call it
with no arguments it will output the MATLAB .m code to create a MATLAB wrapper class.
Paste that code into a .m file. Then you will be able to work with this C++ class
directly in MATLAB.
*/
#include <iostream>
#include <dlib/matrix.h>
using namespace std;
using namespace dlib;
class example_class
{
public:
// The class must have a default constructor. It's also the only kind of constructor
// you can call from MATLAB.
example_class()
{
xx.set_size(3,2);
xx = 1;
}
// The rest of the member functions that you want to bind have to return void and
// generally have the same syntax limitations as regular mex funcitons.
void do_stuff(const matrix_colmajor& x)
{
cout << "in do_stuff" << endl;
cout << x << endl;
xx = x;
}
void do_other_stuff(int x)
{
cout << "in do_other_stuff" << endl;
cout << "x: " << x << endl;
}
void print_state()
{
cout << xx << endl;
}
// saveobj() and load_obj() are special functions. If you provide these then you will
// be able to save() and load() your objects using MATLAB's built in object
// serialization.
void saveobj(matrix_colmajor& state)
{
// save this object's state to state.
state = xx;
}
void load_obj(const matrix_colmajor& state)
{
xx = state;
}
private:
matrix_colmajor xx;
};
// Just tell the mex wrapper the name of your class and list the methods you want to bind.
#define MEX_CLASS_NAME example_class
#define MEX_CLASS_METHODS do_stuff, do_other_stuff, print_state, saveobj, load_obj
#include "mex_wrapper.cpp"
...@@ -102,7 +102,11 @@ ...@@ -102,7 +102,11 @@
#include "../array.h" #include "../array.h"
#include "../image_transforms.h" #include "../image_transforms.h"
#include "../is_kind.h" #include "../is_kind.h"
#include "../string.h"
#include "../any.h" // for sig_traits #include "../any.h" // for sig_traits
#include "../hash.h"
#include <tuple>
#include <map>
#if defined(_MSC_VER) #if defined(_MSC_VER)
#define DLL_EXPORT_SYM __declspec(dllexport) #define DLL_EXPORT_SYM __declspec(dllexport)
...@@ -1165,12 +1169,26 @@ namespace mex_binding ...@@ -1165,12 +1169,26 @@ namespace mex_binding
> >
struct call_mex_function_helper; struct call_mex_function_helper;
template <>
struct call_mex_function_helper<0>
{
template <typename funct>
void callit(
const funct& f,
int , mxArray **,
int , const mxArray **
) const
{
f();
}
};
template <> template <>
struct call_mex_function_helper<1> struct call_mex_function_helper<1>
{ {
template <typename funct> template <typename funct>
void callit( void callit(
const funct& , const funct& f,
int nlhs, mxArray *plhs[], int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[] int nrhs, const mxArray *prhs[]
) const ) const
...@@ -1184,7 +1202,7 @@ namespace mex_binding ...@@ -1184,7 +1202,7 @@ namespace mex_binding
int i = 0; 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<arg1_type>::value) {validate_and_populate_arg(i,prhs[i],A1); ++i;} ELSE_ASSIGN_ARG_1;
mex_function(A1); f(A1);
i = 0; i = 0;
if (is_output_type<arg1_type>::value) {assign_to_matlab(plhs[i],A1); ++i;} if (is_output_type<arg1_type>::value) {assign_to_matlab(plhs[i],A1); ++i;}
...@@ -1196,7 +1214,7 @@ namespace mex_binding ...@@ -1196,7 +1214,7 @@ namespace mex_binding
{ {
template <typename funct> template <typename funct>
void callit( void callit(
const funct& , const funct& f,
int nlhs, mxArray *plhs[], int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[] int nrhs, const mxArray *prhs[]
) const ) const
...@@ -1214,7 +1232,7 @@ namespace mex_binding ...@@ -1214,7 +1232,7 @@ namespace mex_binding
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<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<arg2_type>::value) {validate_and_populate_arg(i,prhs[i],A2); ++i;} ELSE_ASSIGN_ARG_2;
mex_function(A1,A2); f(A1,A2);
i = 0; i = 0;
if (is_output_type<arg1_type>::value) {assign_to_matlab(plhs[i],A1); ++i;} if (is_output_type<arg1_type>::value) {assign_to_matlab(plhs[i],A1); ++i;}
...@@ -1227,7 +1245,7 @@ namespace mex_binding ...@@ -1227,7 +1245,7 @@ namespace mex_binding
{ {
template <typename funct> template <typename funct>
void callit( void callit(
const funct& , const funct& f,
int nlhs, mxArray *plhs[], int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[] int nrhs, const mxArray *prhs[]
) const ) const
...@@ -1249,7 +1267,7 @@ namespace mex_binding ...@@ -1249,7 +1267,7 @@ namespace mex_binding
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<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<arg3_type>::value) {validate_and_populate_arg(i,prhs[i],A3); ++i;} ELSE_ASSIGN_ARG_3;
mex_function(A1,A2,A3); f(A1,A2,A3);
i = 0; i = 0;
if (is_output_type<arg1_type>::value) {assign_to_matlab(plhs[i],A1); ++i;} if (is_output_type<arg1_type>::value) {assign_to_matlab(plhs[i],A1); ++i;}
...@@ -1263,7 +1281,7 @@ namespace mex_binding ...@@ -1263,7 +1281,7 @@ namespace mex_binding
{ {
template <typename funct> template <typename funct>
void callit( void callit(
const funct& , const funct& f,
int nlhs, mxArray *plhs[], int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[] int nrhs, const mxArray *prhs[]
) const ) const
...@@ -1289,7 +1307,7 @@ namespace mex_binding ...@@ -1289,7 +1307,7 @@ namespace mex_binding
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<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<arg4_type>::value) {validate_and_populate_arg(i,prhs[i],A4); ++i;} ELSE_ASSIGN_ARG_4;
mex_function(A1,A2,A3,A4); f(A1,A2,A3,A4);
i = 0; i = 0;
...@@ -1305,7 +1323,7 @@ namespace mex_binding ...@@ -1305,7 +1323,7 @@ namespace mex_binding
{ {
template <typename funct> template <typename funct>
void callit( void callit(
const funct& , const funct& f,
int nlhs, mxArray *plhs[], int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[] int nrhs, const mxArray *prhs[]
) const ) const
...@@ -1335,7 +1353,7 @@ namespace mex_binding ...@@ -1335,7 +1353,7 @@ namespace mex_binding
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<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<arg5_type>::value) {validate_and_populate_arg(i,prhs[i],A5); ++i;} ELSE_ASSIGN_ARG_5;
mex_function(A1,A2,A3,A4,A5); f(A1,A2,A3,A4,A5);
i = 0; i = 0;
...@@ -1353,7 +1371,7 @@ namespace mex_binding ...@@ -1353,7 +1371,7 @@ namespace mex_binding
{ {
template <typename funct> template <typename funct>
void callit( void callit(
const funct& , const funct& f,
int nlhs, mxArray *plhs[], int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[] int nrhs, const mxArray *prhs[]
) const ) const
...@@ -1387,7 +1405,7 @@ namespace mex_binding ...@@ -1387,7 +1405,7 @@ namespace mex_binding
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<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<arg6_type>::value) {validate_and_populate_arg(i,prhs[i],A6); ++i;} ELSE_ASSIGN_ARG_6;
mex_function(A1,A2,A3,A4,A5,A6); f(A1,A2,A3,A4,A5,A6);
i = 0; i = 0;
...@@ -1406,7 +1424,7 @@ namespace mex_binding ...@@ -1406,7 +1424,7 @@ namespace mex_binding
{ {
template <typename funct> template <typename funct>
void callit( void callit(
const funct& , const funct& f,
int nlhs, mxArray *plhs[], int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[] int nrhs, const mxArray *prhs[]
) const ) const
...@@ -1444,7 +1462,7 @@ namespace mex_binding ...@@ -1444,7 +1462,7 @@ namespace mex_binding
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<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<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); f(A1,A2,A3,A4,A5,A6,A7);
i = 0; i = 0;
...@@ -1464,7 +1482,7 @@ namespace mex_binding ...@@ -1464,7 +1482,7 @@ namespace mex_binding
{ {
template <typename funct> template <typename funct>
void callit( void callit(
const funct& , const funct& f,
int nlhs, mxArray *plhs[], int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[] int nrhs, const mxArray *prhs[]
) const ) const
...@@ -1506,7 +1524,7 @@ namespace mex_binding ...@@ -1506,7 +1524,7 @@ namespace mex_binding
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<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<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); f(A1,A2,A3,A4,A5,A6,A7,A8);
i = 0; i = 0;
...@@ -1527,7 +1545,7 @@ namespace mex_binding ...@@ -1527,7 +1545,7 @@ namespace mex_binding
{ {
template <typename funct> template <typename funct>
void callit( void callit(
const funct& , const funct& f,
int nlhs, mxArray *plhs[], int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[] int nrhs, const mxArray *prhs[]
) const ) const
...@@ -1573,7 +1591,7 @@ namespace mex_binding ...@@ -1573,7 +1591,7 @@ namespace mex_binding
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<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<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); f(A1,A2,A3,A4,A5,A6,A7,A8,A9);
i = 0; i = 0;
...@@ -1596,7 +1614,7 @@ namespace mex_binding ...@@ -1596,7 +1614,7 @@ namespace mex_binding
{ {
template <typename funct> template <typename funct>
void callit( void callit(
const funct& , const funct& f,
int nlhs, mxArray *plhs[], int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[] int nrhs, const mxArray *prhs[]
) const ) const
...@@ -1646,7 +1664,7 @@ namespace mex_binding ...@@ -1646,7 +1664,7 @@ namespace mex_binding
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<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; 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); f(A1,A2,A3,A4,A5,A6,A7,A8,A9,A10);
i = 0; i = 0;
...@@ -1668,7 +1686,7 @@ namespace mex_binding ...@@ -1668,7 +1686,7 @@ namespace mex_binding
{ {
template <typename funct> template <typename funct>
void callit( void callit(
const funct& , const funct& f,
int nlhs, mxArray *plhs[], int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[] int nrhs, const mxArray *prhs[]
) const ) const
...@@ -1722,7 +1740,7 @@ namespace mex_binding ...@@ -1722,7 +1740,7 @@ namespace mex_binding
if (i < nrhs && is_input_type<arg10_type>::value) {validate_and_populate_arg(i,prhs[i],A10); ++i;} ELSE_ASSIGN_ARG_10; if (i < nrhs && is_input_type<arg10_type>::value) {validate_and_populate_arg(i,prhs[i],A10); ++i;} ELSE_ASSIGN_ARG_10;
if (i < nrhs && is_input_type<arg11_type>::value) {validate_and_populate_arg(i,prhs[i],A11); ++i;} ELSE_ASSIGN_ARG_11; if (i < nrhs && is_input_type<arg11_type>::value) {validate_and_populate_arg(i,prhs[i],A11); ++i;} ELSE_ASSIGN_ARG_11;
mex_function(A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11); f(A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11);
i = 0; i = 0;
...@@ -1745,7 +1763,7 @@ namespace mex_binding ...@@ -1745,7 +1763,7 @@ namespace mex_binding
{ {
template <typename funct> template <typename funct>
void callit( void callit(
const funct& , const funct& f,
int nlhs, mxArray *plhs[], int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[] int nrhs, const mxArray *prhs[]
) const ) const
...@@ -1803,7 +1821,7 @@ namespace mex_binding ...@@ -1803,7 +1821,7 @@ namespace mex_binding
if (i < nrhs && is_input_type<arg11_type>::value) {validate_and_populate_arg(i,prhs[i],A11); ++i;} ELSE_ASSIGN_ARG_11; if (i < nrhs && is_input_type<arg11_type>::value) {validate_and_populate_arg(i,prhs[i],A11); ++i;} ELSE_ASSIGN_ARG_11;
if (i < nrhs && is_input_type<arg12_type>::value) {validate_and_populate_arg(i,prhs[i],A12); ++i;} ELSE_ASSIGN_ARG_12; if (i < nrhs && is_input_type<arg12_type>::value) {validate_and_populate_arg(i,prhs[i],A12); ++i;} ELSE_ASSIGN_ARG_12;
mex_function(A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12); f(A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12);
i = 0; i = 0;
...@@ -1827,7 +1845,7 @@ namespace mex_binding ...@@ -1827,7 +1845,7 @@ namespace mex_binding
{ {
template <typename funct> template <typename funct>
void callit( void callit(
const funct& , const funct& f,
int nlhs, mxArray *plhs[], int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[] int nrhs, const mxArray *prhs[]
) const ) const
...@@ -1889,7 +1907,7 @@ namespace mex_binding ...@@ -1889,7 +1907,7 @@ namespace mex_binding
if (i < nrhs && is_input_type<arg12_type>::value) {validate_and_populate_arg(i,prhs[i],A12); ++i;} ELSE_ASSIGN_ARG_12; if (i < nrhs && is_input_type<arg12_type>::value) {validate_and_populate_arg(i,prhs[i],A12); ++i;} ELSE_ASSIGN_ARG_12;
if (i < nrhs && is_input_type<arg13_type>::value) {validate_and_populate_arg(i,prhs[i],A13); ++i;} ELSE_ASSIGN_ARG_13; if (i < nrhs && is_input_type<arg13_type>::value) {validate_and_populate_arg(i,prhs[i],A13); ++i;} ELSE_ASSIGN_ARG_13;
mex_function(A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13); f(A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13);
i = 0; i = 0;
...@@ -1914,7 +1932,7 @@ namespace mex_binding ...@@ -1914,7 +1932,7 @@ namespace mex_binding
{ {
template <typename funct> template <typename funct>
void callit( void callit(
const funct& , const funct& f,
int nlhs, mxArray *plhs[], int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[] int nrhs, const mxArray *prhs[]
) const ) const
...@@ -1980,7 +1998,7 @@ namespace mex_binding ...@@ -1980,7 +1998,7 @@ namespace mex_binding
if (i < nrhs && is_input_type<arg13_type>::value) {validate_and_populate_arg(i,prhs[i],A13); ++i;} ELSE_ASSIGN_ARG_13; if (i < nrhs && is_input_type<arg13_type>::value) {validate_and_populate_arg(i,prhs[i],A13); ++i;} ELSE_ASSIGN_ARG_13;
if (i < nrhs && is_input_type<arg14_type>::value) {validate_and_populate_arg(i,prhs[i],A14); ++i;} ELSE_ASSIGN_ARG_14; if (i < nrhs && is_input_type<arg14_type>::value) {validate_and_populate_arg(i,prhs[i],A14); ++i;} ELSE_ASSIGN_ARG_14;
mex_function(A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13,A14); f(A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13,A14);
i = 0; i = 0;
...@@ -2006,7 +2024,7 @@ namespace mex_binding ...@@ -2006,7 +2024,7 @@ namespace mex_binding
{ {
template <typename funct> template <typename funct>
void callit( void callit(
const funct& , const funct& f,
int nlhs, mxArray *plhs[], int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[] int nrhs, const mxArray *prhs[]
) const ) const
...@@ -2076,7 +2094,7 @@ namespace mex_binding ...@@ -2076,7 +2094,7 @@ namespace mex_binding
if (i < nrhs && is_input_type<arg14_type>::value) {validate_and_populate_arg(i,prhs[i],A14); ++i;} ELSE_ASSIGN_ARG_14; if (i < nrhs && is_input_type<arg14_type>::value) {validate_and_populate_arg(i,prhs[i],A14); ++i;} ELSE_ASSIGN_ARG_14;
if (i < nrhs && is_input_type<arg15_type>::value) {validate_and_populate_arg(i,prhs[i],A15); ++i;} ELSE_ASSIGN_ARG_15; if (i < nrhs && is_input_type<arg15_type>::value) {validate_and_populate_arg(i,prhs[i],A15); ++i;} ELSE_ASSIGN_ARG_15;
mex_function(A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13,A14,A15); f(A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13,A14,A15);
i = 0; i = 0;
...@@ -2103,7 +2121,7 @@ namespace mex_binding ...@@ -2103,7 +2121,7 @@ namespace mex_binding
{ {
template <typename funct> template <typename funct>
void callit( void callit(
const funct& , const funct& f,
int nlhs, mxArray *plhs[], int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[] int nrhs, const mxArray *prhs[]
) const ) const
...@@ -2177,7 +2195,7 @@ namespace mex_binding ...@@ -2177,7 +2195,7 @@ namespace mex_binding
if (i < nrhs && is_input_type<arg15_type>::value) {validate_and_populate_arg(i,prhs[i],A15); ++i;} ELSE_ASSIGN_ARG_15; if (i < nrhs && is_input_type<arg15_type>::value) {validate_and_populate_arg(i,prhs[i],A15); ++i;} ELSE_ASSIGN_ARG_15;
if (i < nrhs && is_input_type<arg16_type>::value) {validate_and_populate_arg(i,prhs[i],A16); ++i;} ELSE_ASSIGN_ARG_16; if (i < nrhs && is_input_type<arg16_type>::value) {validate_and_populate_arg(i,prhs[i],A16); ++i;} ELSE_ASSIGN_ARG_16;
mex_function(A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13,A14,A15,A16); f(A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13,A14,A15,A16);
i = 0; i = 0;
...@@ -2205,7 +2223,7 @@ namespace mex_binding ...@@ -2205,7 +2223,7 @@ namespace mex_binding
{ {
template <typename funct> template <typename funct>
void callit( void callit(
const funct& , const funct& f,
int nlhs, mxArray *plhs[], int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[] int nrhs, const mxArray *prhs[]
) const ) const
...@@ -2283,7 +2301,7 @@ namespace mex_binding ...@@ -2283,7 +2301,7 @@ namespace mex_binding
if (i < nrhs && is_input_type<arg16_type>::value) {validate_and_populate_arg(i,prhs[i],A16); ++i;} ELSE_ASSIGN_ARG_16; if (i < nrhs && is_input_type<arg16_type>::value) {validate_and_populate_arg(i,prhs[i],A16); ++i;} ELSE_ASSIGN_ARG_16;
if (i < nrhs && is_input_type<arg17_type>::value) {validate_and_populate_arg(i,prhs[i],A17); ++i;} ELSE_ASSIGN_ARG_17; if (i < nrhs && is_input_type<arg17_type>::value) {validate_and_populate_arg(i,prhs[i],A17); ++i;} ELSE_ASSIGN_ARG_17;
mex_function(A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13,A14,A15,A16,A17); f(A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13,A14,A15,A16,A17);
i = 0; i = 0;
...@@ -2312,7 +2330,7 @@ namespace mex_binding ...@@ -2312,7 +2330,7 @@ namespace mex_binding
{ {
template <typename funct> template <typename funct>
void callit( void callit(
const funct& , const funct& f,
int nlhs, mxArray *plhs[], int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[] int nrhs, const mxArray *prhs[]
) const ) const
...@@ -2394,7 +2412,7 @@ namespace mex_binding ...@@ -2394,7 +2412,7 @@ namespace mex_binding
if (i < nrhs && is_input_type<arg17_type>::value) {validate_and_populate_arg(i,prhs[i],A17); ++i;} ELSE_ASSIGN_ARG_17; if (i < nrhs && is_input_type<arg17_type>::value) {validate_and_populate_arg(i,prhs[i],A17); ++i;} ELSE_ASSIGN_ARG_17;
if (i < nrhs && is_input_type<arg18_type>::value) {validate_and_populate_arg(i,prhs[i],A18); ++i;} ELSE_ASSIGN_ARG_18; if (i < nrhs && is_input_type<arg18_type>::value) {validate_and_populate_arg(i,prhs[i],A18); ++i;} ELSE_ASSIGN_ARG_18;
mex_function(A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13,A14,A15,A16,A17,A18); f(A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13,A14,A15,A16,A17,A18);
i = 0; i = 0;
...@@ -2424,7 +2442,7 @@ namespace mex_binding ...@@ -2424,7 +2442,7 @@ namespace mex_binding
{ {
template <typename funct> template <typename funct>
void callit( void callit(
const funct& , const funct& f,
int nlhs, mxArray *plhs[], int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[] int nrhs, const mxArray *prhs[]
) const ) const
...@@ -2510,7 +2528,7 @@ namespace mex_binding ...@@ -2510,7 +2528,7 @@ namespace mex_binding
if (i < nrhs && is_input_type<arg18_type>::value) {validate_and_populate_arg(i,prhs[i],A18); ++i;} ELSE_ASSIGN_ARG_18; if (i < nrhs && is_input_type<arg18_type>::value) {validate_and_populate_arg(i,prhs[i],A18); ++i;} ELSE_ASSIGN_ARG_18;
if (i < nrhs && is_input_type<arg19_type>::value) {validate_and_populate_arg(i,prhs[i],A19); ++i;} ELSE_ASSIGN_ARG_19; if (i < nrhs && is_input_type<arg19_type>::value) {validate_and_populate_arg(i,prhs[i],A19); ++i;} ELSE_ASSIGN_ARG_19;
mex_function(A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13,A14,A15,A16,A17,A18,A19); f(A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13,A14,A15,A16,A17,A18,A19);
i = 0; i = 0;
...@@ -2541,7 +2559,7 @@ namespace mex_binding ...@@ -2541,7 +2559,7 @@ namespace mex_binding
{ {
template <typename funct> template <typename funct>
void callit( void callit(
const funct& , const funct& f,
int nlhs, mxArray *plhs[], int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[] int nrhs, const mxArray *prhs[]
) const ) const
...@@ -2631,7 +2649,7 @@ namespace mex_binding ...@@ -2631,7 +2649,7 @@ namespace mex_binding
if (i < nrhs && is_input_type<arg19_type>::value) {validate_and_populate_arg(i,prhs[i],A19); ++i;} ELSE_ASSIGN_ARG_19; if (i < nrhs && is_input_type<arg19_type>::value) {validate_and_populate_arg(i,prhs[i],A19); ++i;} ELSE_ASSIGN_ARG_19;
if (i < nrhs && is_input_type<arg20_type>::value) {validate_and_populate_arg(i,prhs[i],A20); ++i;} ELSE_ASSIGN_ARG_20; if (i < nrhs && is_input_type<arg20_type>::value) {validate_and_populate_arg(i,prhs[i],A20); ++i;} ELSE_ASSIGN_ARG_20;
mex_function(A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13,A14,A15,A16,A17,A18,A19,A20); f(A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13,A14,A15,A16,A17,A18,A19,A20);
i = 0; i = 0;
...@@ -2894,25 +2912,8 @@ namespace mex_binding ...@@ -2894,25 +2912,8 @@ namespace mex_binding
sout.str().c_str()); sout.str().c_str());
} }
try
{
call_mex_function_helper<sig_traits<funct>::num_args> helper; call_mex_function_helper<sig_traits<funct>::num_args> helper;
helper.callit(f, nlhs, plhs, nrhs, prhs); 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 (user_hit_ctrl_c& )
{
// do nothing, just return to matlab
}
catch (std::exception& e)
{
mexErrMsgIdAndTxt("mex_function:error",
e.what());
}
} }
...@@ -4534,6 +4535,305 @@ namespace dlib ...@@ -4534,6 +4535,305 @@ namespace dlib
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
#ifdef MEX_CLASS_NAME
template <typename T, typename mfp_type>
class mex_class_wrapper
{
public:
mex_class_wrapper(T& obj_, mfp_type mfp_) : obj(obj_), mfp(mfp_) {}
template <typename... Args>
void operator()(Args&&... args) const
{
(obj.*mfp)(std::forward<Args>(args)...);
}
mfp_type mfp;
T& obj;
};
template <typename T, typename mfp_type>
mex_class_wrapper<T,mfp_type> wrap_mex_class(T& obj, mfp_type mfp) { return mex_class_wrapper<T,mfp_type>(obj, mfp); }
namespace dlib
{
template <typename T, typename mfp_type>
struct sig_traits<mex_class_wrapper<T,mfp_type>>
: public sig_traits<mfp_type>
{};
template <size_t i, typename T, bool is_good = i < std::tuple_size<T>::value>
struct tuple_element_default_void
{
typedef void type;
};
template <size_t i, typename T>
struct tuple_element_default_void<i,T,true>
{
typedef typename std::tuple_element<i,T>::type type;
};
template <typename class_type, typename return_type, typename... Args>
struct sig_traits<return_type(class_type::*)(Args...) >
{
enum { num_args = sizeof...(Args) };
typedef return_type result_type;
template <size_t i>
struct arg
{
typedef typename tuple_element_default_void<i-1, std::tuple<Args...>>::type type;
};
// These are here because that's how things are defined in sig_traits (since it is
// older than C++11, along with most of the other code in this file)
typedef typename arg<1>::type arg1_type;
typedef typename arg<2>::type arg2_type;
typedef typename arg<3>::type arg3_type;
typedef typename arg<4>::type arg4_type;
typedef typename arg<5>::type arg5_type;
typedef typename arg<6>::type arg6_type;
typedef typename arg<7>::type arg7_type;
typedef typename arg<8>::type arg8_type;
typedef typename arg<9>::type arg9_type;
typedef typename arg<10>::type arg10_type;
typedef typename arg<11>::type arg11_type;
typedef typename arg<12>::type arg12_type;
typedef typename arg<13>::type arg13_type;
typedef typename arg<14>::type arg14_type;
typedef typename arg<15>::type arg15_type;
typedef typename arg<16>::type arg16_type;
typedef typename arg<17>::type arg17_type;
typedef typename arg<18>::type arg18_type;
typedef typename arg<19>::type arg19_type;
typedef typename arg<20>::type arg20_type;
};
template <typename class_type, typename return_type, typename... Args>
struct sig_traits<return_type(class_type::*)(Args...) const>
{
enum { num_args = sizeof...(Args) };
typedef return_type result_type;
template <size_t i>
struct arg
{
typedef typename tuple_element_default_void<i-1, std::tuple<Args...>>::type type;
};
// These are here because that's how things are defined in sig_traits (since it is
// older than C++11, along with most of the other code in this file)
typedef typename arg<1>::type arg1_type;
typedef typename arg<2>::type arg2_type;
typedef typename arg<3>::type arg3_type;
typedef typename arg<4>::type arg4_type;
typedef typename arg<5>::type arg5_type;
typedef typename arg<6>::type arg6_type;
typedef typename arg<7>::type arg7_type;
typedef typename arg<8>::type arg8_type;
typedef typename arg<9>::type arg9_type;
typedef typename arg<10>::type arg10_type;
typedef typename arg<11>::type arg11_type;
typedef typename arg<12>::type arg12_type;
typedef typename arg<13>::type arg13_type;
typedef typename arg<14>::type arg14_type;
typedef typename arg<15>::type arg15_type;
typedef typename arg<16>::type arg16_type;
typedef typename arg<17>::type arg17_type;
typedef typename arg<18>::type arg18_type;
typedef typename arg<19>::type arg19_type;
typedef typename arg<20>::type arg20_type;
};
}
// ----------------------------------------------------------------------------------------
template <size_t I>
struct visit_impl
{
template <typename T, typename F>
static void visit(T& tup, size_t idx, F fun)
{
if (idx == I - 1) fun(std::get<I - 1>(tup));
else visit_impl<I - 1>::visit(tup, idx, fun);
}
};
template <>
struct visit_impl<0>
{
template <typename T, typename F>
static void visit(T& tup, size_t idx, F fun) { DLIB_CASSERT(false,"this should never happen"); }
};
template <typename F, typename... Ts>
void visit_at(std::tuple<Ts...> const& tup, size_t idx, F fun)
{
visit_impl<sizeof...(Ts)>::visit(tup, idx, fun);
}
template <typename F, typename... Ts>
void visit_at(std::tuple<Ts...>& tup, size_t idx, F fun)
{
visit_impl<sizeof...(Ts)>::visit(tup, idx, fun);
}
class mex_class_dispatch
{
public:
mex_class_dispatch(
MEX_CLASS_NAME* ptr_,
int nlhs_,
mxArray** plhs_,
int nrhs_,
const mxArray** prhs_
) :
ptr(ptr_),
nlhs(nlhs_),
plhs(plhs_),
nrhs(nrhs_),
prhs(prhs_)
{}
template <typename funct>
void operator() (const funct& mfp)
{
mex_binding::call_mex_function(wrap_mex_class(*ptr,mfp), nlhs, plhs, nrhs, prhs);
}
private:
MEX_CLASS_NAME* ptr;
int nlhs;
mxArray** plhs;
int nrhs;
const mxArray** prhs;
};
class class_factory_type : dlib::noncopyable
{
/*!
WHAT THIS OBJECT REPRESENTS
This is a container class for all the MEX_CLASS_NAME objects we create. It allows
us to track what we have created and make sure the MATLAB user doesn't do any
double frees or use any stale pointers.
It also helps us deal with the problem that would otherwise arise when a mex file
is unloaded from MATLAB when there are still active pointers to MEX_CLASS_NAME objects
in MATLAB, since we will be able to detect stale pointers.
!*/
public:
class_factory_type()
{
seed = (uint64)time(0);
}
~class_factory_type()
{
for (auto i : object_table)
delete i.second;
}
uint64 create()
{
MEX_CLASS_NAME* item = new MEX_CLASS_NAME;
uint64 id = (uint64)item;
// Now generate a unique id that incorporates our seed value. The point of doing
// this is to avoid any chance that a mex file will get unloaded and then reloaded
// and start constructing objects with the same addresses, while old stale objects
// at those addresses are still stored in matlab, which would then call into the
// mex file and make things go crazy. So here we try to generate ID numbers that
// are globally unique.
uint64 i = 0;
id = murmur_hash3_128bit_3(id, seed, ++i).first;
// very unlikely but make sure there aren't any hash collisions.
while(object_table.count(id) != 0)
id = murmur_hash3_128bit_3(id, seed, ++i).first;
object_table[id] = item;
return id;
}
void free(uint64 item)
{
if (object_table.count(item) == 0)
{
throw dlib::error("An attempt to deallocate a mex class object with an invalid pointer was detected.");
}
delete object_table[item];
object_table.erase(item);
}
MEX_CLASS_NAME* access(uint64 item) // convert numeric ID to pointer to object that can be used.
{
if (object_table.count(item) == 0)
{
throw dlib::error("An attempt to access a mex class object with an invalid pointer was detected.");
}
return object_table[item];
}
private:
std::map<uint64, MEX_CLASS_NAME*> object_table;
uint64 seed;
} class_factory;
// ----------------------------------------------------------------------------------------
// Make a FOREACH macro
#define FE_1(WHAT, X) WHAT(X)
#define FE_2(WHAT, X, ...) WHAT(X),FE_1(WHAT, __VA_ARGS__)
#define FE_3(WHAT, X, ...) WHAT(X),FE_2(WHAT, __VA_ARGS__)
#define FE_4(WHAT, X, ...) WHAT(X),FE_3(WHAT, __VA_ARGS__)
#define FE_5(WHAT, X, ...) WHAT(X),FE_4(WHAT, __VA_ARGS__)
#define FE_6(WHAT, X, ...) WHAT(X),FE_5(WHAT, __VA_ARGS__)
#define FE_7(WHAT, X, ...) WHAT(X),FE_6(WHAT, __VA_ARGS__)
#define FE_8(WHAT, X, ...) WHAT(X),FE_7(WHAT, __VA_ARGS__)
#define FE_9(WHAT, X, ...) WHAT(X),FE_8(WHAT, __VA_ARGS__)
#define FE_10(WHAT, X, ...) WHAT(X),FE_9(WHAT, __VA_ARGS__)
#define FE_11(WHAT, X, ...) WHAT(X),FE_10(WHAT, __VA_ARGS__)
#define FE_12(WHAT, X, ...) WHAT(X),FE_11(WHAT, __VA_ARGS__)
#define FE_13(WHAT, X, ...) WHAT(X),FE_12(WHAT, __VA_ARGS__)
#define FE_14(WHAT, X, ...) WHAT(X),FE_13(WHAT, __VA_ARGS__)
#define FE_15(WHAT, X, ...) WHAT(X),FE_14(WHAT, __VA_ARGS__)
#define FE_16(WHAT, X, ...) WHAT(X),FE_15(WHAT, __VA_ARGS__)
#define FE_17(WHAT, X, ...) WHAT(X),FE_16(WHAT, __VA_ARGS__)
#define FE_18(WHAT, X, ...) WHAT(X),FE_17(WHAT, __VA_ARGS__)
#define FE_19(WHAT, X, ...) WHAT(X),FE_18(WHAT, __VA_ARGS__)
#define FE_20(WHAT, X, ...) WHAT(X),FE_19(WHAT, __VA_ARGS__)
//... repeat as needed
#define GET_MACRO(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,NAME,...) NAME
#define FOR_EACH(action,...) GET_MACRO(__VA_ARGS__,FE_20,FE_19,FE_18,FE_17,FE_16,FE_15,FE_14,FE_13,FE_12,FE_11,FE_10,FE_9,FE_8,FE_7,FE_6,FE_5,FE_4,FE_3,FE_2,FE_1)(action,__VA_ARGS__)
#define MEX_CLASS_ANNOTATE(x) &MEX_CLASS_NAME::x
// Now make a tuple containing all the member function pointers to our MEX_CLASS_NAME
auto mex_class_methods = std::make_tuple(FOR_EACH(MEX_CLASS_ANNOTATE, MEX_CLASS_METHODS));
#endif // MEX_CLASS_NAME
// ----------------------------------------------------------------------------------------
bool is_string_construct(const mxArray* arr)
{
if (mxIsChar(arr) && mxGetNumberOfElements(arr) == 9)
{
char ch[20];
DLIB_CASSERT(mxGetString(arr, ch, sizeof(ch))==0, "Unable to retrieve string");
return strcmp("construct",ch)==0;
}
return false;
}
// ----------------------------------------------------------------------------------------
/* The gateway function called by MATLAB*/ /* The gateway function called by MATLAB*/
void mexFunction( int nlhs, mxArray *plhs[], void mexFunction( int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[]) int nrhs, const mxArray *prhs[])
...@@ -4546,7 +4846,122 @@ void mexFunction( int nlhs, mxArray *plhs[], ...@@ -4546,7 +4846,122 @@ void mexFunction( int nlhs, mxArray *plhs[],
mex_binding::mex_warn_streambuf wsb; mex_binding::mex_warn_streambuf wsb;
#endif #endif
try
{
#ifdef MEX_CLASS_NAME
if (nrhs == 0)
{
#define DEF2STR(x) DEF2STR2((x))
#define DEF2STR2(x) #x
string classname = trim(string(DEF2STR(MEX_CLASS_NAME)), " \t()");
std::vector<string> methods = split(trim(string(DEF2STR(MEX_CLASS_METHODS)), " \t()"), " \t,");
string mex_filename = "mex_"+classname;
bool has_load_obj = false;
size_t load_obj_idx = 0;
cout << "classdef " << classname << " < handle\n"
<< " properties (Access = private)\n"
<< " cpp_ptr\n"
<< " end\n"
<< "\n"
<< " methods\n"
<< " function this = "<<classname<<"()\n"
<< " this.cpp_ptr = "<<mex_filename<<"('construct');\n"
<< " end\n"
<< "\n";
for (size_t i = 0; i < methods.size(); ++i)
{
if (methods[i] == "load_obj")
{
has_load_obj = true;
load_obj_idx = i;
}
else
{
cout << " function varargout = "<<methods[i]<<"(this, varargin) \n"
<< " [varargout{1:nargout}] = "<<mex_filename<<"(this.cpp_ptr, "<<i+1<<", varargin{:}); \n"
<< " end \n\n";
}
}
cout << " end\n\n";
cout << " methods(Access=private) \n"
<< " function delete(this) \n"
<< " "<<mex_filename<<"(this.cpp_ptr); \n"
<< " end \n";
if (has_load_obj)
{
cout << " function varargout = load_obj(this, varargin) \n"
<< " [varargout{1:nargout}] = "<<mex_filename<<"(this.cpp_ptr, "<<load_obj_idx+1<<", varargin{:}); \n"
<< " end \n";
}
cout << " end \n\n";
if (has_load_obj)
{
cout << " methods(Static) \n"
<< " function this = loadobj(in) \n"
<< " this = "<<classname<<"(); \n"
<< " this.load_obj(in); \n"
<< " end \n"
<< " end \n"
<< "end \n";
}
}
else if (nrhs == 1)
{
// this is a constructor call
if (is_string_construct(prhs[0]))
{
plhs[0] = mxCreateNumericMatrix(1, 1, mxUINT64_CLASS, mxREAL);
uint64* ptr_int = (uint64*)mxGetData(plhs[0]);
*ptr_int = class_factory.create();
}
else // destructor call
{
DLIB_CASSERT(mxIsUint64(prhs[0]) && mxGetNumberOfElements(prhs[0])==1, "When calling a class destructor the first argument must be a pointer (a UINT64 in matlab)");
const uint64 ptr_int = *((uint64*)mxGetData(prhs[0]));
class_factory.free(ptr_int);
}
}
else // a regular function call
{
DLIB_CASSERT(mxIsUint64(prhs[0]) && mxGetNumberOfElements(prhs[0])==1, "When calling a class member function the first argument must be a pointer (a UINT64 in matlab)");
DLIB_CASSERT(mxIsDouble(prhs[1]) && mxGetNumberOfElements(prhs[1])==1, "When calling a class member function the second argument must be a number indicating which member function");
const uint64 ptr_int = *((uint64*)mxGetData(prhs[0]));
const int funct_idx = *(mxGetPr(prhs[1]));
auto num_registered_functions = std::tuple_size<decltype(mex_class_methods)>::value;
DLIB_CASSERT(1 <= funct_idx && funct_idx <= num_registered_functions, "Invalid function index provided.");
MEX_CLASS_NAME* ptr = class_factory.access(ptr_int);
// we used the first two arguments to decide what function to call. So adjust nrhs
// and prhs so the member function never sees them.
mex_class_dispatch dispatch(ptr, nlhs, plhs, nrhs-2, prhs+2);
// now invoke the member function, subtract 1 to convert to 0 indexing.
visit_at(mex_class_methods, funct_idx-1, dispatch);
}
#else
mex_binding::call_mex_function(mex_function, nlhs, plhs, nrhs, prhs); mex_binding::call_mex_function(mex_function, nlhs, plhs, nrhs, prhs);
#endif
}
catch (mex_binding::invalid_args_exception& e)
{
mexErrMsgIdAndTxt("mex_function:validate_and_populate_arg",
("Input" + e.msg).c_str());
}
catch (mex_binding::user_hit_ctrl_c& )
{
// do nothing, just return to matlab
}
catch (std::exception& e)
{
mexErrMsgIdAndTxt("mex_function:error",
e.what());
}
cout << flush; cout << flush;
cerr << flush; cerr << flush;
......
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