Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
D
dlib
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
钟尚武
dlib
Commits
060cdd09
Commit
060cdd09
authored
Jan 28, 2016
by
Davis King
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added struct support to matlab to C++ API
parent
27274c17
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
311 additions
and
1 deletion
+311
-1
CMakeLists.txt
dlib/matlab/CMakeLists.txt
+1
-0
call_matlab.h
dlib/matlab/call_matlab.h
+54
-0
example_mex_struct.cpp
dlib/matlab/example_mex_struct.cpp
+55
-0
mex_wrapper.cpp
dlib/matlab/mex_wrapper.cpp
+201
-1
No files found.
dlib/matlab/CMakeLists.txt
View file @
060cdd09
...
...
@@ -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 @
060cdd09
...
...
@@ -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 @
060cdd09
// 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 @
060cdd09
...
...
@@ -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