Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
OpenFlipper-Free
OpenFlipper
Commits
cef4e5aa
Commit
cef4e5aa
authored
Jan 22, 2019
by
Jan Möbius
Browse files
Initial commit of the python interpreter
parent
6caf8265
Changes
3
Hide whitespace changes
Inline
Side-by-side
PythonInterpreter/PyLogHook.h
0 → 100644
View file @
cef4e5aa
//MIT License
//
//Copyright(c) 2017 Matthias Möller
//https://github.com/TinyTinni/PyLogHook
//
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files(the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions :
//
//The above copyright notice and this permission notice shall be included in all
//copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//SOFTWARE.
#pragma once
#include
<utility>
#include
<string>
#ifdef TYTI_PYLOGHOOK_USE_BOOST
#include
<boost/python.hpp>
#else
#include
<pybind11/pybind11.h>
#endif
namespace
tyti
{
namespace
pylog
{
namespace
detail
{
#ifdef TYTI_PYLOGHOOK_USE_BOOST
template
<
typename
T
>
inline
boost
::
python
::
object
LogHookMakeObject
(
T
t
)
{
return
boost
::
python
::
object
(
boost
::
python
::
make_function
(
std
::
forward
<
T
>
(
t
),
boost
::
python
::
default_call_policies
(),
boost
::
mpl
::
vector
<
void
,
const
char
*>
()
// signature
));
}
#else
template
<
typename
T
>
inline
pybind11
::
object
LogHookMakeObject
(
T
t
)
{
return
pybind11
::
cpp_function
(
std
::
forward
<
T
>
(
t
));
}
#endif
template
<
typename
T
>
void
redirect_syspipe
(
T
t
,
const
char
*
pipename
)
{
assert
(
Py_IsInitialized
());
PyObject
*
out
=
PySys_GetObject
(
pipename
);
// in case python couldnt create stdout/stderr
// this happens in some gui application
// just register a new nameless type for this
if
(
out
==
NULL
||
out
==
Py_None
)
{
std
::
string
register_read_write
=
std
::
string
(
"import sys
\n
\
sys."
)
+
pipename
+
std
::
string
(
" = type(
\"\"
,(object,),{
\"
write
\"
:lambda self, txt: None,
\"
flush
\"
:lambda self: None})()
\n
"
);
PyRun_SimpleString
(
register_read_write
.
c_str
());
out
=
PySys_GetObject
(
pipename
);
}
// overwrite write function
PyObject_SetAttrString
(
out
,
"write"
,
detail
::
LogHookMakeObject
(
std
::
forward
<
T
>
(
t
)).
ptr
());
}
}
// namespace detail
/** \brief redirects sys.stdout
Whenever sys.stdout.write is called, call the given function instead.
Given function has to be the signature "void (const char*)"
Preconditions:
Python has to be initialized.
Calling thread has to hold the GIL. (in case of multi threading)
Exceptions:
Maybe a PyErr occurs. This must be handled by the user.
@param t callbacl function of type "void (const char*)"
*/
template
<
typename
T
>
inline
void
redirect_stdout
(
T
t
)
{
detail
::
redirect_syspipe
(
std
::
forward
<
T
>
(
t
),
"stdout"
);
}
template
<
typename
T
>
inline
void
redirect_stderr
(
T
t
)
{
detail
::
redirect_syspipe
(
std
::
forward
<
T
>
(
t
),
"stderr"
);
}
}
}
PythonInterpreter/PythonInterpreter.cc
0 → 100644
View file @
cef4e5aa
/*===========================================================================*\
* *
* OpenFlipper *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openflipper.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenFlipper. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
\*===========================================================================*/
#include
<pybind11/include/pybind11/pybind11.h>
#include
<pybind11/include/pybind11/embed.h>
#include
"PyLogHook.h"
#include
"PythonInterpreter.hh"
namespace
py
=
pybind11
;
static
Core
*
core_
;
static
pybind11
::
module
mainModule_
;
static
PythonInterpreter
*
interpreter_
=
nullptr
;
/** \brief Stores a clean dictionary for interpreter reset
*
*/
static
PyObject
*
global_dict_clean_
=
nullptr
;
void
setCorePointer
(
Core
*
_core
)
{
core_
=
_core
;
}
PythonInterpreter
*
PythonInterpreter
::
getInstance
()
{
if
(
interpreter_
==
nullptr
)
{
interpreter_
=
new
PythonInterpreter
();
}
return
interpreter_
;
}
PythonInterpreter
::
PythonInterpreter
()
{
}
PythonInterpreter
::~
PythonInterpreter
()
{
}
bool
PythonInterpreter
::
modulesInitialized
()
{
///@TODO: Why does this work?
return
static_cast
<
bool
>
(
mainModule_
);
}
void
PythonInterpreter
::
initPython
()
{
if
(
Py_IsInitialized
()
)
return
;
std
::
cerr
<<
"A"
<<
std
::
endl
;
py
::
initialize_interpreter
();
std
::
cerr
<<
"B"
<<
std
::
endl
;
PyEval_InitThreads
();
std
::
cerr
<<
"C"
<<
std
::
endl
;
if
(
!
modulesInitialized
())
{
std
::
cerr
<<
"D"
<<
std
::
endl
;
//dlopen("libpython3.5m.so.1.0", RTLD_LAZY | RTLD_GLOBAL);
py
::
module
main
{
py
::
module
::
import
(
"__main__"
)
};
// redirect python output
tyti
::
pylog
::
redirect_stderr
([
this
](
const
char
*
w
)
{
this
->
pyError
(
w
);
});
tyti
::
pylog
::
redirect_stdout
([
this
](
const
char
*
w
)
{
this
->
pyOutput
(
w
);
});
std
::
cerr
<<
"E"
<<
std
::
endl
;
// add openflipper module
py
::
object
main_namespace
=
main
.
attr
(
"__dict__"
);
std
::
cerr
<<
"F"
<<
std
::
endl
;
py
::
module
of_module
(
py
::
module
::
import
(
"openflipper"
));
main_namespace
[
"openflipper"
]
=
of_module
;
std
::
cerr
<<
"G"
<<
std
::
endl
;
global_dict_clean_
=
PyDict_Copy
(
PyModule_GetDict
(
main
.
ptr
()));
std
::
cerr
<<
"H"
<<
std
::
endl
;
// set the main module member to a validate state, shows, that all modules are successfully initialized
mainModule_
=
std
::
move
(
main
);
std
::
cerr
<<
"I"
<<
std
::
endl
;
// Do not release the GIL until all modules are initalzed
PyEval_SaveThread
();
std
::
cerr
<<
"J"
<<
std
::
endl
;
}
}
void
PythonInterpreter
::
resetInterpreter
()
{
if
(
!
Py_IsInitialized
()
||
!
modulesInitialized
())
return
;
PyGILState_STATE
state
=
PyGILState_Ensure
();
PyObject
*
dict
=
PyModule_GetDict
(
mainModule_
.
ptr
());
PyDict_Clear
(
dict
);
PyDict_Update
(
dict
,
global_dict_clean_
);
PyGILState_Release
(
state
);
}
bool
PythonInterpreter
::
runScript
(
QString
_script
)
{
std
::
cerr
<<
"runScript"
<<
std
::
endl
;
// init
try
{
std
::
cerr
<<
"Run Init Python"
<<
std
::
endl
;
initPython
();
std
::
cerr
<<
".. Done"
<<
std
::
endl
;
}
catch
(
py
::
error_already_set
&
e
)
{
pyError
(
e
.
what
());
return
false
;
}
PyGILState_STATE
state
=
PyGILState_Ensure
();
PyThreadState
*
tstate
=
PyGILState_GetThisThreadState
();
auto
locals
=
mainModule_
.
attr
(
"__dict__"
);
bool
result
=
true
;
try
{
std
::
cerr
<<
"Now executing script"
<<
std
::
endl
;
py
::
exec
((
const
char
*
)
_script
.
toLatin1
(),
py
::
globals
(),
locals
);
std
::
cerr
<<
"Finished successfully"
<<
std
::
endl
;
}
catch
(
py
::
error_already_set
&
e
)
{
pyError
(
e
.
what
());
e
.
restore
();
result
=
false
;
}
catch
(
const
std
::
runtime_error
&
e
)
{
pyError
(
e
.
what
());
pyOutput
(
"Restarting Interpreter."
);
resetInterpreter
();
result
=
false
;
state
=
PyGILState_Ensure
();
}
PyGILState_Release
(
state
);
return
result
;
}
// Python callback functions
void
PythonInterpreter
::
pyOutput
(
const
char
*
w
)
{
std
::
cerr
<<
"Python output:
\n
"
<<
w
<<
std
::
endl
;
Q_EMIT
log
(
LOGOUT
,
QString
(
w
));
}
void
PythonInterpreter
::
pyError
(
const
char
*
w
)
{
std
::
cerr
<<
"Python error:
\n
"
<<
w
<<
std
::
endl
;
Q_EMIT
log
(
LOGERR
,
QString
(
w
));
}
int
add
(
int
i
,
int
j
)
{
return
i
+
j
;
}
//import openflipper
//
//a = openflipper.core()
//
//a.updateView()
//print("AAAAAAAAAAAA")
//a = openflipper.core()
//
//print("BBBBBBBBBB")
//a.updateView()
//print("CCCCCCCCCc")
PYBIND11_EMBEDDED_MODULE
(
openflipper
,
m
)
{
py
::
class_
<
Core
>
core
(
m
,
"core"
);
// core
// .def("__init__",
// [](Core &instance) {
// return core_;
// } );
core
.
def
(
py
::
init
([]()
{
return
core_
;
}));
// core.def("__del__",
// +[](const Core&) -> void {
// std::cerr << "deleting Core" << std::endl;
// });
core
.
def
(
"updateView"
,
&
Core
::
updateView
);
core
.
def
(
"updateView"
,
&
Core
::
updateView
);
core
.
def
(
"clearAll"
,
&
Core
::
clearAll
);
// m.def("targets", &targets);
// m.def("sources", &sources);
// m.def("meshes", &meshes);
//
// m.def("updateView", &Core::updateView);
// m.def("clearAll", &Core::clearAll);
std
::
cerr
<<
"CorePointer : "
<<
core_
<<
std
::
endl
;;
}
PYBIND11_EMBEDDED_MODULE
(
examples
,
m
)
{
m
.
doc
()
=
"pybind11 example plugin"
;
// optional module docstring
m
.
def
(
"add"
,
&
add
,
"A function which adds two numbers"
);
}
PythonInterpreter/PythonInterpreter.hh
0 → 100644
View file @
cef4e5aa
/*===========================================================================*\
* *
* OpenFlipper *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openflipper.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenFlipper. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
\*===========================================================================*/
#pragma once
#include
<OpenFlipper/Core/Core.hh>
/** \brief This class provides OpenFlippers Python interpreter
*
*/
class
PythonInterpreter
:
public
QObject
{
Q_OBJECT
signals:
/// Log with OUT,WARN or ERR as type
void
log
(
Logtype
_type
,
QString
_message
);
/// Default logging as OUT
void
log
(
QString
_message
);
public:
~
PythonInterpreter
();
/** \brief Creates or returns an instance of the interpreter
*
* There will only be one instance of the PythonInterpreter to ensure
* that we only run one context.
*
* @return
*/
static
PythonInterpreter
*
getInstance
();
bool
runScript
(
QString
_script
);
private:
/** \brief private constructor because of singleton
*
*/
PythonInterpreter
();
/** \brief Initialize OpenFlipper Python Interpreter
*
*/
void
initPython
();
/** \brief Resets the interpreter and all states
*
*/
void
resetInterpreter
();
bool
modulesInitialized
();
/** \brief Callback to redirect cout log to OpenFlipper logger
*
* @param w Log string
*/
void
pyOutput
(
const
char
*
w
);
/** \brief Callback to redirect cerr log to OpenFlipper logger
*
* @param w Log string
*/
void
pyError
(
const
char
*
w
);
};
/** \brief give Core pointer to PythonInterpreter for exporting of Core functionality to python
*
* This function is called by OpenFlipper.cc to pass a pointer of the OpenFlipper Core to
* the python side. This allows the PythonInterpreter class to export functions from the core
* and call them directly.
*
* @param _core Pointer to OpenFlipper application core
*/
void
setCorePointer
(
Core
*
_core
);
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new 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