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
ba59ddc6
Commit
ba59ddc6
authored
May 31, 2016
by
Davis King
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added subprocess_stream so that complex things can be isolated from MATLAB's
shenanigans in a separate process.
parent
0d2bce15
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
211 additions
and
0 deletions
+211
-0
subprocess_stream.cpp
dlib/matlab/subprocess_stream.cpp
+0
-0
subprocess_stream.h
dlib/matlab/subprocess_stream.h
+211
-0
No files found.
dlib/matlab/subprocess_stream.cpp
0 → 100644
View file @
ba59ddc6
This diff is collapsed.
Click to expand it.
dlib/matlab/subprocess_stream.h
0 → 100644
View file @
ba59ddc6
// Copyright (C) 2016 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_SUBPROCeSS_STREAM_H_
#define DLIB_SUBPROCeSS_STREAM_H_
#include <utility>
#include <unistd.h>
#include <iostream>
#include <memory>
#include <dlib/matrix.h>
namespace
dlib
{
// --------------------------------------------------------------------------------------
// Call dlib's serialize and deserialize by default. The point of this version of
// serailize is to do something fast that normally we wouldn't do, like directly copy
// memory. This is safe since this is an interprocess communication happening the same
// machine.
template
<
typename
T
>
void
interprocess_serialize
(
const
T
&
item
,
std
::
ostream
&
out
)
{
serialize
(
item
,
out
);
}
template
<
typename
T
>
void
interprocess_deserialize
(
T
&
item
,
std
::
istream
&
in
)
{
deserialize
(
item
,
in
);
}
// But have overloads for direct memory copies for some types since this is faster than
// their default serialization.
template
<
typename
T
,
long
NR
,
long
NC
,
typename
MM
,
typename
L
>
void
interprocess_serialize
(
const
dlib
::
matrix
<
T
,
NR
,
NC
,
MM
,
L
>&
item
,
std
::
ostream
&
out
)
{
dlib
::
serialize
(
item
.
nr
(),
out
);
dlib
::
serialize
(
item
.
nc
(),
out
);
if
(
item
.
size
()
!=
0
)
out
.
write
((
const
char
*
)
&
item
(
0
,
0
),
sizeof
(
T
)
*
item
.
size
());
if
(
!
out
)
throw
dlib
::
serialization_error
(
"Error writing matrix to interprocess iostream."
);
}
template
<
typename
T
,
long
NR
,
long
NC
,
typename
MM
,
typename
L
>
void
interprocess_deserialize
(
dlib
::
matrix
<
T
,
NR
,
NC
,
MM
,
L
>&
item
,
std
::
istream
&
in
)
{
long
nr
,
nc
;
dlib
::
deserialize
(
nr
,
in
);
dlib
::
deserialize
(
nc
,
in
);
item
.
set_size
(
nr
,
nc
);
if
(
item
.
size
()
!=
0
)
in
.
read
((
char
*
)
&
item
(
0
,
0
),
sizeof
(
T
)
*
item
.
size
());
if
(
!
in
)
throw
dlib
::
serialization_error
(
"Error reading matrix from interprocess iostream."
);
}
// ----------------------------------------------------------------------------------------
inline
void
send_to_parent_process
()
{
std
::
cout
.
flush
();}
template
<
typename
U
,
typename
...
T
>
void
send_to_parent_process
(
U
&&
arg1
,
T
&&
...
args
)
/*!
ensures
- sends all the arguments to send_to_parent_process() to standard output (and
hence to the parent process) by serializing them with
interprocess_serialize().
!*/
{
interprocess_serialize
(
arg1
,
std
::
cout
);
send_to_parent_process
(
std
::
forward
<
T
>
(
args
)...);
if
(
!
std
::
cout
)
throw
dlib
::
error
(
"Error sending object to parent process."
);
}
inline
void
receive_from_parent_process
()
{}
template
<
typename
U
,
typename
...
T
>
void
receive_from_parent_process
(
U
&&
arg1
,
T
&&
...
args
)
/*!
ensures
- receives all the arguments to receive_from_parent_process() from standard
input (and hence from the parent process) by deserializing them with
interprocess_deserialize().
!*/
{
interprocess_deserialize
(
arg1
,
std
::
cin
);
receive_from_parent_process
(
std
::
forward
<
T
>
(
args
)...);
if
(
!
std
::
cin
)
throw
dlib
::
error
(
"Error receiving object from parent process."
);
}
// ----------------------------------------------------------------------------------------
class
filestreambuf
;
class
subprocess_stream
:
public
std
::
iostream
{
/*!
WHAT THIS OBJECT REPRESENTS
This is a tool for spawning a subprocess and communicating with it through
that processes standard input, output, and error. Here is an example:
subprocess_stream s("/usr/bin/echo")
s << "echo me this!";
string line;
getline(s, line);
cout << line << endl;
s.wait();
That example runs echo, sends it some text, gets it back, and prints it to
the screen. Then it waits for the subprocess to finish.
!*/
public
:
explicit
subprocess_stream
(
const
char
*
program_name
);
/*!
ensures
- spawns a sub process by executing the file with the given program_name.
!*/
~
subprocess_stream
(
);
/*!
ensures
- calls wait(). Note that the destructor never throws even though wait() can.
If an exception is thrown by wait() it is just logged to std::cerr.
!*/
void
wait
(
);
/*!
ensures
- closes the standard input of the child process and then waits for the
child to terminate.
- If the child returns an error (by returning != 0 from its main) or
outputs to its standard error then wait() throws a dlib::error() with the
standard error output in it.
!*/
int
get_child_pid
()
const
{
return
child_pid
;
}
/*!
ensures
- returns the PID of the child process
!*/
template
<
typename
U
,
typename
...
T
>
void
send
(
U
&&
arg1
,
T
&&
...
args
)
/*!
ensures
- sends all the arguments to send() to the subprocess by serializing them
with interprocess_serialize().
!*/
{
interprocess_serialize
(
arg1
,
*
this
);
send
(
std
::
forward
<
T
>
(
args
)...);
if
(
!
this
->
good
())
{
std
::
ostringstream
sout
;
sout
<<
stderr
.
rdbuf
();
throw
dlib
::
error
(
"Error sending object to child process.
\n
"
+
sout
.
str
());
}
}
void
send
()
{
this
->
flush
();}
template
<
typename
U
,
typename
...
T
>
void
receive
(
U
&&
arg1
,
T
&&
...
args
)
/*!
ensures
- receives all the arguments to receive() to the subprocess by deserializing
them with interprocess_deserialize().
!*/
{
interprocess_deserialize
(
arg1
,
*
this
);
receive
(
std
::
forward
<
T
>
(
args
)...);
if
(
!
this
->
good
())
{
std
::
ostringstream
sout
;
sout
<<
stderr
.
rdbuf
();
throw
dlib
::
error
(
"Error receiving object from child process.
\n
"
+
sout
.
str
()
);
}
}
void
receive
()
{}
private
:
void
send_eof
();
class
cpipe
{
private
:
int
fd
[
2
];
public
:
cpipe
()
{
if
(
pipe
(
fd
))
throw
dlib
::
error
(
"Failed to create pipe"
);
}
~
cpipe
()
{
close
();
}
int
read_fd
()
const
{
return
fd
[
0
];
}
int
write_fd
()
const
{
return
fd
[
1
];
}
void
close
()
{
::
close
(
fd
[
0
]);
::
close
(
fd
[
1
]);
}
};
cpipe
write_pipe
;
cpipe
read_pipe
;
cpipe
err_pipe
;
bool
wait_called
=
false
;
std
::
unique_ptr
<
filestreambuf
>
inout_buf
=
NULL
;
std
::
unique_ptr
<
filestreambuf
>
err_buf
=
NULL
;
int
child_pid
=
-
1
;
std
::
istream
stderr
;
};
}
// ----------------------------------------------------------------------------------------
#endif // DLIB_SUBPROCeSS_STREAM_H_
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