Skip to content

Commit

Permalink
Add the FGLogger feature to the Python module.
Browse files Browse the repository at this point in the history
  • Loading branch information
bcoconni committed Nov 10, 2024
1 parent d04edb8 commit b57db80
Show file tree
Hide file tree
Showing 9 changed files with 358 additions and 20 deletions.
5 changes: 3 additions & 2 deletions python/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ configure_file(${SIMGEAR_XML_SOURCE_DIR}/xmltok_impl.c
configure_file(${SIMGEAR_XML_SOURCE_DIR}/xmltok_ns.c
${CMAKE_CURRENT_BINARY_DIR}/src/simgear/xml/xmltok_ns.c COPYONLY)

foreach(_FILE "MANIFEST.in" "ExceptionManagement.h" "fpectl/fpectlmodule.h" "pyproject.toml")
foreach(_FILE "MANIFEST.in" "ExceptionManagement.h" "PyLogger.h" "PyLogger.cxx" "fpectl/fpectlmodule.h" "pyproject.toml")
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/${_FILE} ${CMAKE_CURRENT_BINARY_DIR}/${_FILE} COPYONLY)
endforeach()
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/JSBSim.py ${CMAKE_CURRENT_BINARY_DIR}/JSBSim.py COPYONLY)
Expand Down Expand Up @@ -105,7 +105,8 @@ file(RELATIVE_PATH BUILD_ROOT_PATH ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_BINARY_DI

configure_file(setup.py.in ${CMAKE_CURRENT_BINARY_DIR}/setup.py)

python3_add_library(_jsbsim MODULE ${JSBSIM_CXX} ${CMAKE_CURRENT_SOURCE_DIR}/ExceptionManagement.h)
python3_add_library(_jsbsim MODULE ${JSBSIM_CXX}
${CMAKE_CURRENT_SOURCE_DIR}/PyLogger.cxx)
target_include_directories(_jsbsim PRIVATE ${PROJECT_SOURCE_DIR}/src)
target_link_libraries(_jsbsim PRIVATE libJSBSim)
set_target_properties(_jsbsim PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${JSBSIM_TEST_PACKAGE_DIR})
Expand Down
24 changes: 17 additions & 7 deletions python/ExceptionManagement.h
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
/* Convert JSBSim exceptions to Python exceptions
*
* Copyright (c) 2016 Bertrand Coconnier
* Copyright (c) 2016-2024 Bertrand Coconnier
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 3 of the License, or (at your option) any later
* version.
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, see <http://www.gnu.org/licenses/>
* You should have received a copy of the GNU Lesser General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Further information about the GNU Lesser General Public License can also be
* found on the world wide web at http://www.gnu.org.
*/

#include <string>
Expand All @@ -23,6 +27,10 @@
#include "math/FGMatrix33.h"
#include "math/FGTable.h"

#ifndef EXCEPTIONMANAGEMENT_H
#define EXCEPTIONMANAGEMENT_H

namespace JSBSim {
// Pointers to Python exception classes.
// Their initialization take place in jsbsim.pyx
PyObject* base_error;
Expand Down Expand Up @@ -55,3 +63,5 @@ void convertJSBSimToPyExc()
PyErr_SetString(PyExc_RuntimeError, msg);
}
}
}
#endif // EXCEPTIONMANAGEMENT_H
176 changes: 176 additions & 0 deletions python/PyLogger.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Header: PyLog.cxx
Author: Bertrand Coconnier
Date started: 11/02/24
------------- Copyright (C) 2024 Bertrand Coconnier -------------
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your option) any
later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details.
You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Further information about the GNU Lesser General Public License can also be
found on the world wide web at http://www.gnu.org.
*/

#include <cassert>
#include "PyLogger.h"

namespace JSBSim {
// These pointers are initialized in jsbsim.pyx
PyObject* FGLogger_PyClass;
PyObject* LogLevel_PyClass;
PyObject* LogFormat_PyClass;

/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CLASS IMPLEMENTATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/

PyLogger::PyLogger(PyObject* logger)
{
if (PyObject_IsInstance(logger, FGLogger_PyClass)) {
logger_pyclass = logger;
Py_INCREF(logger_pyclass);
} else {
PyErr_SetString(PyExc_TypeError, "The logger must be an instance of FGLogger");
}
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

void PyLogger::SetLevel(LogLevel level) {
PyObject* py_level;

switch (level)
{
case LogLevel::BULK:
py_level = PyObject_GetAttrString(LogLevel_PyClass, "BULK");
break;
case LogLevel::DEBUG:
py_level = PyObject_GetAttrString(LogLevel_PyClass, "DEBUG");
break;
case LogLevel::INFO:
py_level = PyObject_GetAttrString(LogLevel_PyClass, "INFO");
break;
case LogLevel::WARN:
py_level = PyObject_GetAttrString(LogLevel_PyClass, "WARN");
break;
case LogLevel::ERROR:
py_level = PyObject_GetAttrString(LogLevel_PyClass, "ERROR");
break;
case LogLevel::FATAL:
py_level = PyObject_GetAttrString(LogLevel_PyClass, "FATAL");
break;
}

bool success = CallPythonMethodWithArguments("set_level", py_level);
if (success) FGLogger::SetLevel(level);
Py_DECREF(py_level);
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

void PyLogger::FileLocation(const std::string& filename, int line)
{
PyObject* py_filename = PyUnicode_FromString(filename.c_str());
PyObject* py_line = PyLong_FromLong(line);
PyObject* args = PyTuple_Pack(2, py_filename, py_line);
CallPythonMethodWithTuple("file_location", args);
Py_DECREF(args);
Py_DECREF(py_filename);
Py_DECREF(py_line);
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

void PyLogger::Message(const std::string& message)
{
PyObject* msg = PyUnicode_FromString(message.c_str());
CallPythonMethodWithArguments("message", msg);
Py_DECREF(msg);
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

void PyLogger::Format(LogFormat format)
{
PyObject* py_format;

switch (format)
{
case LogFormat::RESET:
py_format = PyObject_GetAttrString(LogFormat_PyClass, "RESET");
break;
case LogFormat::RED:
py_format = PyObject_GetAttrString(LogFormat_PyClass, "RED");
break;
case LogFormat::BLUE:
py_format = PyObject_GetAttrString(LogFormat_PyClass, "BLUE");
break;
case LogFormat::CYAN:
py_format = PyObject_GetAttrString(LogFormat_PyClass, "CYAN");
break;
case LogFormat::GREEN:
py_format = PyObject_GetAttrString(LogFormat_PyClass, "GREEN");
break;
case LogFormat::DEFAULT:
py_format = PyObject_GetAttrString(LogFormat_PyClass, "DEFAULT");
break;
case LogFormat::BOLD:
py_format = PyObject_GetAttrString(LogFormat_PyClass, "BOLD");
break;
case LogFormat::NORMAL:
py_format = PyObject_GetAttrString(LogFormat_PyClass, "NORMAL");
break;
case LogFormat::UNDERLINE_ON:
py_format = PyObject_GetAttrString(LogFormat_PyClass, "UNDERLINE_ON");
break;
case LogFormat::UNDERLINE_OFF:
py_format = PyObject_GetAttrString(LogFormat_PyClass, "UNDERLINE_OFF");
break;
}

CallPythonMethodWithArguments("format", py_format);
Py_DECREF(py_format);
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

bool PyLogger::CallPythonMethodWithArguments(const char* method_name, PyObject* arg)
{
PyObject* tuple = PyTuple_Pack(1, arg);
bool success = CallPythonMethodWithTuple(method_name, tuple);
Py_DECREF(tuple);
return success;
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

bool PyLogger::CallPythonMethodWithTuple(const char* method_name, PyObject* tuple)
{
PyObject* method = PyObject_GetAttrString(logger_pyclass, method_name);
assert(method); // This should not fail as the constructor has checked the type of logger_pyclass.

PyObject* result = PyObject_CallObject(method, tuple);
Py_DECREF(method);

if (result) {
Py_DECREF(result);
return true;
}

PyErr_Print();
return false;
}
} // namespace JSBSim
57 changes: 57 additions & 0 deletions python/PyLogger.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Header: PyLog.h
Author: Bertrand Coconnier
Date started: 11/02/24
------------- Copyright (C) 2024 Bertrand Coconnier -------------
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your option) any
later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details.
You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Further information about the GNU Lesser General Public License can also be
found on the world wide web at http://www.gnu.org.
*/

#include <Python.h>
#include "input_output/FGLog.h"

#ifndef PYLOG_H
#define PYLOG_H

namespace JSBSim {
/// Pointers to the Python counterparts of C++ classes.
extern PyObject* FGLogger_PyClass;
extern PyObject* LogLevel_PyClass;
extern PyObject* LogFormat_PyClass;

class PyLogger : public FGLogger
{
public:
explicit PyLogger(PyObject* logger);
~PyLogger() override { Py_XDECREF(logger_pyclass); }
void SetLevel(LogLevel level) override;
void FileLocation(const std::string& filename, int line) override;
void Message(const std::string& message) override;
void Format(LogFormat format) override;
void Flush(void) override { CallPythonMethodWithTuple("flush", nullptr); }

private:
bool CallPythonMethodWithTuple(const char* method_name, PyObject* tuple);
bool CallPythonMethodWithArguments(const char* method_name, PyObject* arg);

PyObject* logger_pyclass = nullptr;
};
}
#endif
3 changes: 3 additions & 0 deletions python/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,16 @@
FGJSBBase,
FGLGear,
FGLinearization,
FGLogger,
FGMassBalance,
FGPropagate,
FGPropertyManager,
FGPropertyNode,
FGPropulsion,
GeographicError,
TrimFailureError,
LogLevel,
LogFormat,
ePressure,
eTemperature,
get_default_root_dir,
Expand Down
24 changes: 16 additions & 8 deletions python/fpectl/fpectlmodule.h
Original file line number Diff line number Diff line change
@@ -1,25 +1,32 @@
/* Python module to control floating point exceptions
*
* Copyright (c) 2016 Bertrand Coconnier
* Copyright (c) 2016-2024 Bertrand Coconnier
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 3 of the License, or (at your option) any later
* version.
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, see <http://www.gnu.org/licenses/>
* You should have received a copy of the GNU Lesser General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Further information about the GNU Lesser General Public License can also be
* found on the world wide web at http://www.gnu.org.
*/

#include "Python.h"
#include <Python.h>
#include <exception>
#include <string>

#ifndef FPCTLMODULE_H
#define FPCTLMODULE_H

namespace JSBSim {
class FloatingPointException: public std::exception
{
Expand All @@ -35,3 +42,4 @@ class FloatingPointException: public std::exception
std::string msg;
};
}
#endif // FPCTLMODULE_H
10 changes: 9 additions & 1 deletion python/jsbsim.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ from libcpp.memory cimport shared_ptr
from libcpp.vector cimport vector
from cpython.ref cimport PyObject

cdef extern from "ExceptionManagement.h":
cdef extern from "ExceptionManagement.h" namespace "JSBSim":
cdef PyObject* base_error
cdef PyObject* trimfailure_error
cdef PyObject* geographic_error
Expand Down Expand Up @@ -86,6 +86,13 @@ cdef extern from "input_output/FGPropertyManager.h" namespace "JSBSim":
c_FGPropertyNode* GetNode(const string& path, bool create)
bool HasNode(const string& path) except +convertJSBSimToPyExc

cdef extern from "PyLogger.h" namespace "JSBSim":
cdef PyObject* FGLogger_PyClass
cdef PyObject* LogLevel_PyClass
cdef PyObject* LogFormat_PyClass
cdef cppclass c_PyLogger "JSBSim::PyLogger":
c_PyLogger(PyObject* logger)

cdef extern from "math/FGColumnVector3.h" namespace "JSBSim":
cdef cppclass c_FGColumnVector3 "JSBSim::FGColumnVector3":
c_FGColumnVector3()
Expand Down Expand Up @@ -261,3 +268,4 @@ cdef extern from "FGFDMExec.h" namespace "JSBSim":
shared_ptr[c_FGAircraft] GetAircraft()
shared_ptr[c_FGAtmosphere] GetAtmosphere()
shared_ptr[c_FGMassBalance] GetMassBalance()
void SetLogger(shared_ptr[c_PyLogger] logger)
Loading

0 comments on commit b57db80

Please sign in to comment.