No practical purpose, just curious. For PythonCall
in Julia code, it’s easy to imagine that a Julia wrapper increments an underlying CPython object’s reference count to protect it from CPython’s GC (I don’t know if this is actually true, so please correct me). But I can’t imagine how juliacall
in Python code can protect underlying Julia objects from Julia’s GC when there isn’t an explicit Julia program to start tracing from. Is there a hidden juliacall
cache of Julia objects somewhere, and if so can I get a link to its implementation?
Here it is: PythonCall.jl/src/JlWrap/C.jl at 71666ca0a30eafee2456a191fa2490cdd0b0ed22 · JuliaPy/PythonCall.jl · GitHub
Pretty simple really, we keep a global vector containing all of the wrapped Julia values and the Python wrapper just holds the index into this vector.
And when the Python wrapper is deleted, the corresponding entry in the vector is set to nothing
so the wrapped value can be GC’d.
Am I assuming correctly this vector is mutated by __del__
finalization? source
link for juliacall.AnyValue
on the docs site doesn’t take me to a .py file, weirdly a directory in the base Julia Github.
The type is implemented in Julia not Python, and the __del__
implementation is just a few lines down, here: PythonCall.jl/src/JlWrap/C.jl at 71666ca0a30eafee2456a191fa2490cdd0b0ed22 · JuliaPy/PythonCall.jl · GitHub
As for the link in the docs - we have some hacky shenanigans to document Python things using Documenter.jl so I’m not surprised that’s broken.