I’m looking into extending Python with Julia code through PyJulia, particularly allocating numpy arrays in Python, passing them to Julia (without copying) to do some processing and then use the result in Python again. This seems to be the reverse of what many other users are doing (i.e. using PyCall
from Julia to call into Python), so maybe what I want is not supported.
But looking at the docs for PyCall, specifically GitHub - JuliaPy/PyCall.jl: Package to call Python functions from the Julia language, seems to suggest it is possible to pass a NumPy array from Python to Julia without copying:
Alternatively, the PyCall module also provides a new type
PyArray
(a subclass ofAbstractArray
) which implements a no-copy wrapper around a NumPy array (currently of numeric types or objects only). Just usePyArray
as the return type of apycall
returning anndarray
, or callPyArray(o::PyObject)
on anndarray
objecto
. (Technically, aPyArray
works for any Python object that uses the NumPy array interface to provide a data pointer and shape information.)
However, the referenced PyArray
type lives on the Julia side so I can’t call it on the Python side. Using a Julia function with signature fn(x::PyArray)
also doesn’t seem to do automatic conversion, as I get a no method matching fn(::Array{Float32,2})
error when called from Python with:
melis@juggle 15:33:~$ cat fn.jl
function fn(x::PyArray)
println("array size: $(size(x))");
println("max element: $(maximum(x))")
println("min element: $(minimum(x))")
x[1,1] = 123
return 2x
end
melis@juggle 15:33:~$ cat callit.py
from julia.api import Julia
from julia import Main
jl = Julia(compiled_modules=False)
jl.eval('include("fn.jl")')
import numpy as np
x = np.array([[1,2,3], [4,5,6]], dtype=np.float64)
res = Main.fn(x)
melis@juggle 15:34:~$ python callit.py
Traceback (most recent call last):
File "callit.py", line 11, in <module>
res = Main.fn(x)
RuntimeError: Julia exception: MethodError: no method matching fn(::Array{Float64,2})
Closest candidates are:
fn(!Matched::PyArray) at /home/melis/concepts/blender-julia/fn.jl:1
Stacktrace:
[1] #invokelatest#1 at ./essentials.jl:710 [inlined]
[2] invokelatest(::Any, ::Any) at ./essentials.jl:709
[3] _pyjlwrap_call(::Function, ::Ptr{PyCall.PyObject_struct}, ::Ptr{PyCall.PyObject_struct}) at /home/melis/.julia/packages/PyCall/zqDXB/src/callback.jl:28
[4] pyjlwrap_call(::Ptr{PyCall.PyObject_struct}, ::Ptr{PyCall.PyObject_struct}, ::Ptr{PyCall.PyObject_struct}) at /home/melis/.julia/packages/PyCall/zqDXB/src/callback.jl:49
Any other ways to make this work?
Edit: word