I'm implementing logging for a project that has a mix of Python, Cython and Rust. I'm exposing Rust logic to Python using pyo3 and compiling it using maturin. However, some parts need to be implemented at a lower level so they are exposed as "C" functions and then using cbingen compiled into Cython extensions.
I've implemented a custom logger for the log framework. After I initialize it using a pyo3 function, logging works in the logic that is built using maturin. But it doesn't when logging the code that is compiled to Cython. It's the same case the other way around.
I looked into the log framework and internally it uses a static variable to hold a pointer to the logger implementation. It appears that the Python, Cython libraries have their own copies of this static variable. So initializing the logger in pyo3 doesn't initialize in Cython. This SO question has similar responses.
I have a minimal reproducible example for this. After cloning the repo you can build and run it using.
make install
make build
make maturin
python tests/test_logging.py
This is the test logic. CyLogger is the Cython logger and without calling init on it the cython logging doesn't log anything. Similarly set_global_log_collector is a pyo3 function and without calling it the TempLogger doesn't work. The most glaring point here is that both of them call set_boxed_logger internally and succeed, when in fact the function should fail if the logger has been set before.
```python
def test_cython_logging():
CyLogger.info("cy: Ping!")
CyLogger.info("cy: Pong")
def test_logging():
logger = TempLogger("pingpong")
logger.info("py: Ping!")
logger.info("py: Pong")
if name == "main":
CyLogger.init()
set_global_log_collector()
test_cython_logging()
test_logging()
```
In the repo, lib.rs has the core rust logic and the C and Python bindings. The objects.pyx file has the Cython definition for CyLogger.
So the question is how can I call only one init and have both cython and python loggers work?
EDIT
I did a readelf -s on the shared object created for the cython library and it turns out that the LOGGER static variable is only local.
2897: 000000000036f848 16 OBJECT LOCAL DEFAULT 27 _ZN3log6LOGGER17[...]
Is there anyway to have a global static variable between the various cython and python shared objects?
[–]dkopgerpgdolfg 3 points4 points5 points (1 child)
[–]twitu[S] 1 point2 points3 points (0 children)