Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
OpenDAS
dlib
Commits
7b67bd2f
Commit
7b67bd2f
authored
Jan 28, 2016
by
Davis King
Browse files
merged
parents
d479bf85
060cdd09
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
311 additions
and
1 deletion
+311
-1
dlib/matlab/CMakeLists.txt
dlib/matlab/CMakeLists.txt
+1
-0
dlib/matlab/call_matlab.h
dlib/matlab/call_matlab.h
+54
-0
dlib/matlab/example_mex_struct.cpp
dlib/matlab/example_mex_struct.cpp
+55
-0
dlib/matlab/mex_wrapper.cpp
dlib/matlab/mex_wrapper.cpp
+201
-1
No files found.
dlib/matlab/CMakeLists.txt
View file @
7b67bd2f
...
...
@@ -12,4 +12,5 @@ include(../cmake)
# add_mex_function(some_other_mex_function pthread dlib fftw)
add_mex_function
(
example_mex_function dlib
)
add_mex_function
(
example_mex_callback dlib
)
add_mex_function
(
example_mex_struct dlib
)
dlib/matlab/call_matlab.h
View file @
7b67bd2f
...
...
@@ -6,6 +6,60 @@
#include <string>
// ----------------------------------------------------------------------------------------
class
matlab_struct
{
/*!
WHAT THIS OBJECT REPRESENTS
This object lets you interface with MATLAB structs from C++. For example,
given a MATLAB struct named mystruct, you could access it's fields like this:
MATLAB way: mystruct.field
C++ way: mystruct["field"]
MATLAB way: mystruct.field.subfield
C++ way: mystruct["field"]["subfield"]
To get the values as C++ types you do something like this:
int val = mystruct["field"];
See also example_mex_struct.cpp for an example that uses this part of the API.
!*/
class
sub
;
public:
matlab_struct
()
:
struct_handle
(
0
),
should_free
(
false
)
{}
~
matlab_struct
();
const
sub
operator
[]
(
const
std
::
string
&
name
)
const
;
sub
operator
[]
(
const
std
::
string
&
name
);
bool
has_field
(
const
std
::
string
&
name
)
const
;
const
void
*
release_struct_to_matlab
()
{
const
void
*
temp
=
struct_handle
;
struct_handle
=
0
;
return
temp
;
}
void
set_struct_handle
(
const
void
*
sh
)
{
struct_handle
=
sh
;
}
private:
class
sub
{
public:
sub
()
:
struct_handle
(
0
),
field_idx
(
-
1
)
{}
template
<
typename
T
>
operator
T
()
const
;
template
<
typename
T
>
sub
&
operator
=
(
const
T
&
new_val
);
const
sub
operator
[]
(
const
std
::
string
&
name
)
const
;
sub
operator
[]
(
const
std
::
string
&
name
);
bool
has_field
(
const
std
::
string
&
name
)
const
;
private:
friend
class
matlab_struct
;
const
void
*
struct_handle
;
int
field_idx
;
sub
&
operator
=
(
const
sub
&
);
};
const
void
*
struct_handle
;
bool
should_free
;
matlab_struct
&
operator
=
(
const
matlab_struct
&
);
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
...
...
dlib/matlab/example_mex_struct.cpp
0 → 100644
View file @
7b67bd2f
// The contents of this file are in the public domain. See LICENSE_FOR_EXAMPLE_PROGRAMS.txt
#include "call_matlab.h"
#include "dlib/matrix.h"
using
namespace
dlib
;
using
namespace
std
;
/*
This mex function takes a MATLAB struct, prints a few of its fields,
and then returns a new struct.
For example, you can call this function in MATLAB like so:
input = {}
input.val = 2
input.stuff = 'some string'
output = example_mex_struct(input)
output.number
output.number2
output.sub.stuff
output.sub.some_matrix
*/
void
mex_function
(
const
matlab_struct
&
input
,
matlab_struct
&
output
)
{
int
val
=
input
[
"val"
];
string
stuff
=
input
[
"stuff"
];
if
(
input
.
has_field
(
"val2"
))
{
string
val2
=
input
[
"val2"
];
cout
<<
"The optional val2 field was set to: "
<<
val2
<<
endl
;
}
cout
<<
"val: "
<<
val
<<
endl
;
cout
<<
"stuff: "
<<
stuff
<<
endl
;
output
[
"number"
]
=
999
;
output
[
"number2"
]
=
1000
;
output
[
"sub"
][
"stuff"
]
=
"some other string"
;
matrix
<
double
>
m
=
randm
(
2
,
2
);
output
[
"sub"
][
"some_matrix"
]
=
m
;
}
// #including this brings in all the mex boiler plate needed by MATLAB.
#include "mex_wrapper.cpp"
dlib/matlab/mex_wrapper.cpp
View file @
7b67bd2f
...
...
@@ -711,6 +711,23 @@ namespace mex_binding
}
}
void
validate_and_populate_arg
(
long
arg_idx
,
const
mxArray
*
prhs
,
matlab_struct
&
arg
)
{
if
(
!
mxIsStruct
(
prhs
))
{
std
::
ostringstream
sout
;
sout
<<
" argument "
<<
arg_idx
+
1
<<
" must be a struct"
;
throw
invalid_args_exception
(
sout
.
str
());
}
arg
.
set_struct_handle
(
prhs
);
}
void
validate_and_populate_arg
(
long
arg_idx
,
const
mxArray
*
prhs
,
...
...
@@ -737,7 +754,6 @@ namespace mex_binding
arg
.
resize
(
size
);
}
// ----------------------------------------------------------------------------------------
template
<
typename
EXP
>
...
...
@@ -904,6 +920,14 @@ namespace mex_binding
}
}
void
assign_to_matlab
(
mxArray
*&
plhs
,
matlab_struct
&
item
)
{
plhs
=
(
mxArray
*
)
item
.
release_struct_to_matlab
();
}
void
assign_to_matlab
(
mxArray
*&
plhs
,
const
std
::
string
&
item
...
...
@@ -2164,6 +2188,182 @@ void call_matlab (
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template
<
typename
T
>
matlab_struct
::
sub
::
operator
T
()
const
{
if
(
struct_handle
==
0
)
throw
dlib
::
error
(
"Attempt to access data in an empty struct."
);
mxArray
*
temp
=
mxGetFieldByNumber
((
const
mxArray
*
)
struct_handle
,
0
,
field_idx
);
if
(
temp
==
0
)
throw
dlib
::
error
(
"Attempt to access data in an empty struct."
);
T
item
;
try
{
mex_binding
::
validate_and_populate_arg
(
0
,
temp
,
item
);
}
catch
(
mex_binding
::
invalid_args_exception
&
e
)
{
std
::
ostringstream
sout
;
sout
<<
"Struct field '"
<<
mxGetFieldNameByNumber
((
const
mxArray
*
)
struct_handle
,
field_idx
)
<<
"' can't be interpreted as the requested type."
<<
endl
<<
e
.
msg
;
throw
dlib
::
error
(
sout
.
str
());
}
return
item
;
}
const
matlab_struct
::
sub
matlab_struct
::
operator
[]
(
const
std
::
string
&
name
)
const
{
if
(
struct_handle
==
0
)
throw
dlib
::
error
(
"Struct does not have a field named '"
+
name
+
"'."
);
matlab_struct
::
sub
temp
;
temp
.
struct_handle
=
struct_handle
;
temp
.
field_idx
=
mxGetFieldNumber
((
const
mxArray
*
)
struct_handle
,
name
.
c_str
());
if
(
temp
.
field_idx
==
-
1
)
throw
dlib
::
error
(
"Struct does not have a field named '"
+
name
+
"'."
);
return
temp
;
}
matlab_struct
::
sub
matlab_struct
::
operator
[]
(
const
std
::
string
&
name
)
{
if
(
struct_handle
==
0
)
{
// We make a struct from scratch and mark that we will free it unless it gets
// written back to matlab by assign_to_matlab().
mwSize
dims
[
1
]
=
{
1
};
const
char
*
name_str
=
name
.
c_str
();
struct_handle
=
mxCreateStructArray
(
1
,
dims
,
1
,
&
name_str
);
should_free
=
true
;
if
(
struct_handle
==
0
)
throw
dlib
::
error
(
"Error creating struct from within mex function."
);
}
matlab_struct
::
sub
temp
;
temp
.
struct_handle
=
struct_handle
;
if
((
temp
.
field_idx
=
mxGetFieldNumber
((
mxArray
*
)
struct_handle
,
name
.
c_str
()))
==
-
1
)
{
if
((
temp
.
field_idx
=
mxAddField
((
mxArray
*
)
struct_handle
,
name
.
c_str
()))
==
-
1
)
{
throw
dlib
::
error
(
"Unable to add field '"
+
name
+
"' to struct."
);
}
}
return
temp
;
}
const
matlab_struct
::
sub
matlab_struct
::
sub
::
operator
[]
(
const
std
::
string
&
name
)
const
{
if
(
struct_handle
==
0
)
throw
dlib
::
error
(
"Struct does not have a field named '"
+
name
+
"'."
);
matlab_struct
::
sub
temp
;
temp
.
struct_handle
=
mxGetFieldByNumber
((
const
mxArray
*
)
struct_handle
,
0
,
field_idx
);
if
(
temp
.
struct_handle
==
0
)
throw
dlib
::
error
(
"Failure to get struct field while calling mxGetFieldByNumber()"
);
if
(
!
mxIsStruct
((
const
mxArray
*
)
temp
.
struct_handle
))
throw
dlib
::
error
(
"Struct sub-field element '"
+
name
+
"' is not another struct."
);
temp
.
field_idx
=
mxGetFieldNumber
((
const
mxArray
*
)
temp
.
struct_handle
,
name
.
c_str
());
if
(
temp
.
field_idx
==
-
1
)
throw
dlib
::
error
(
"Struct does not have a field named '"
+
name
+
"'."
);
return
temp
;
}
matlab_struct
::
sub
matlab_struct
::
sub
::
operator
[]
(
const
std
::
string
&
name
)
{
if
(
struct_handle
==
0
)
throw
dlib
::
error
(
"Struct does not have a field named '"
+
name
+
"'."
);
matlab_struct
::
sub
temp
;
temp
.
struct_handle
=
mxGetFieldByNumber
((
const
mxArray
*
)
struct_handle
,
0
,
field_idx
);
// We are replacing this field with a struct if it exists and isn't already a struct
if
(
temp
.
struct_handle
!=
0
&&
!
mxIsStruct
((
const
mxArray
*
)
temp
.
struct_handle
))
{
mxDestroyArray
((
mxArray
*
)
temp
.
struct_handle
);
temp
.
struct_handle
=
0
;
}
if
(
temp
.
struct_handle
==
0
)
{
mwSize
dims
[
1
]
=
{
1
};
temp
.
struct_handle
=
mxCreateStructArray
(
1
,
dims
,
0
,
0
);
if
(
temp
.
struct_handle
==
0
)
throw
dlib
::
error
(
"Failure to create new sub-struct field"
);
mxSetFieldByNumber
((
mxArray
*
)
struct_handle
,
0
,
field_idx
,
(
mxArray
*
)
temp
.
struct_handle
);
}
if
((
temp
.
field_idx
=
mxGetFieldNumber
((
mxArray
*
)
temp
.
struct_handle
,
name
.
c_str
()))
==
-
1
)
{
if
((
temp
.
field_idx
=
mxAddField
((
mxArray
*
)
temp
.
struct_handle
,
name
.
c_str
()))
==
-
1
)
{
throw
dlib
::
error
(
"Unable to add field '"
+
name
+
"' to struct."
);
}
}
return
temp
;
}
bool
matlab_struct
::
has_field
(
const
std
::
string
&
name
)
const
{
if
(
struct_handle
==
0
)
return
false
;
return
mxGetFieldNumber
((
const
mxArray
*
)
struct_handle
,
name
.
c_str
())
!=
-
1
;
}
bool
matlab_struct
::
sub
::
has_field
(
const
std
::
string
&
name
)
const
{
if
(
struct_handle
==
0
)
return
false
;
mxArray
*
temp
=
mxGetFieldByNumber
((
const
mxArray
*
)
struct_handle
,
0
,
field_idx
);
if
(
temp
==
0
||
!
mxIsStruct
(
temp
))
return
false
;
return
mxGetFieldNumber
(
temp
,
name
.
c_str
())
!=
-
1
;
}
template
<
typename
T
>
matlab_struct
::
sub
&
matlab_struct
::
sub
::
operator
=
(
const
T
&
new_val
)
{
// Delete anything in the field before we overwrite it
mxArray
*
item
=
mxGetFieldByNumber
((
mxArray
*
)
struct_handle
,
0
,
field_idx
);
if
(
item
!=
0
)
{
mxDestroyArray
((
mxArray
*
)
item
);
item
=
0
;
}
// Now set the field
mex_binding
::
assign_to_matlab
(
item
,
new_val
);
mxSetFieldByNumber
((
mxArray
*
)
struct_handle
,
0
,
field_idx
,
item
);
return
*
this
;
}
matlab_struct
::
~
matlab_struct
(
)
{
if
(
struct_handle
&&
should_free
)
{
mxDestroyArray
((
mxArray
*
)
struct_handle
);
struct_handle
=
0
;
}
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
void
call_matlab
(
const
function_handle
&
funct
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment