Skip to content

Python binding of FGLogger#1406

Merged
bcoconni merged 11 commits intoJSBSim-Team:masterfrom
bcoconni:PyLog
Mar 31, 2026
Merged

Python binding of FGLogger#1406
bcoconni merged 11 commits intoJSBSim-Team:masterfrom
bcoconni:PyLog

Conversation

@bcoconni
Copy link
Copy Markdown
Member

This PR exposes the class FGLogger and the function SetLogger to the Python module to allow managing JSBSim logged output from Python.

User manual

It defines the Python class FGLogger that can be inherited and passed to set_logger:

class FGLogger:
    log_level = LogLevel.BULK

    def set_level(self, level: LogLevel) -> None:
        self.log_level = level
    def file_location(self, filename: str, line: int) -> None:
        pass
    def message(self, message: str) -> None:
        pass
    def format(self, format: LogFormat) -> None:
        pass
    def flush(self) -> None:
        pass

A trivial example is given in jsbsim.pyx.in:

class DefaultLogger(FGLogger):
    def file_location(self, filename: str, line: int) -> None:
        print(f"\nIn file {filename}: line {line}")
    def message(self, message: str) -> None:
        print(f"{message}", end='')

then a class instance can be passed to JSBSim using set_logger:

set_logger(DefaultLogger())

Under the hood

  • A new C++ class PyLogger is defined which inherits from the C++ class FGLogger. It basically passes the data received from the C++ code to the Python class that has been set via set_logger.
  • The headers fpectlmodule.h and ExceptionManagement.h have been protected against multiple inclusions using #ifdef FPECTLMODULE_H and #ifdef EXCEPTIONMANAGEMENT_H.
  • The definitions in ExceptionManagement.h are now in the C++ namespace JSBSim, especially since it uses quite generic names such as base_error.
  • A new class PyObjectPtr is defined that uses RAII to properly manage the different calls to Py_INCREF and Py_DECREF, calls which otherwise are a mess to manage.

There is a subtlety in the order in which the objects are destroyed at exit. It happens that Py_Finalize() is called before the C++ destructors so the instance of the C++ class PyLogger may be destroyed after all the Python objects have been deleted which could result in a SEGFAULT.

To prevent this error from happening a small function _reset_logger() is passed to atexit in order to be called by Py_Finalize. This allows the PyLogger instance to be destroyed before the Python objects it is pointing to are destroyed themselves.

@bcoconni bcoconni changed the title Python binding to FGLogger Python binding of FGLogger Mar 15, 2026
@codecov
Copy link
Copy Markdown

codecov bot commented Mar 15, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 25.23%. Comparing base (98c0333) to head (e59838e).
⚠️ Report is 7 commits behind head on master.

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #1406   +/-   ##
=======================================
  Coverage   25.23%   25.23%           
=======================================
  Files         169      169           
  Lines       18631    18631           
=======================================
  Hits         4701     4701           
  Misses      13930    13930           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@seanmcleod70
Copy link
Copy Markdown
Contributor

Looks good.

@bcoconni bcoconni merged commit fc8156d into JSBSim-Team:master Mar 31, 2026
30 checks passed
@bcoconni
Copy link
Copy Markdown
Member Author

Thanks. PR merged.

@bcoconni bcoconni deleted the PyLog branch March 31, 2026 07:54
@bcoconni
Copy link
Copy Markdown
Member Author

Hmm... The CI is failing following the merge of this PR. This seems to be due to the changes introduced by the PR #1405 that trigger the following assert:

assert(method); // This should not fail as the constructor has checked the type of logger_pyclass.

@seanmcleod70
Copy link
Copy Markdown
Contributor

Need to display the method_name during the assert to figure out what method is being requested?

@bcoconni
Copy link
Copy Markdown
Member Author

bcoconni commented Apr 1, 2026

Need to display the method_name during the assert to figure out what method is being requested?

I have submitted the PR #1413 that fixes the issue.

bcoconni added a commit that referenced this pull request Apr 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants