-
Notifications
You must be signed in to change notification settings - Fork 67
/
Copy pathobjectarray.jl
101 lines (87 loc) · 2.97 KB
/
objectarray.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
"""
PyObjectArray(undef, dims...)
PyObjectArray(array)
An array of `Py`s which supports the Python buffer protocol.
Internally, the objects are stored as an array of pointers.
"""
mutable struct PyObjectArray{N} <: AbstractArray{Py,N}
ptrs::Array{C.PyPtr,N}
function PyObjectArray{N}(::UndefInitializer, dims::NTuple{N,Integer}) where {N}
x = new{N}(fill(C.PyNULL, dims))
finalizer(pyobjectarray_finalizer, x)
end
end
const PyObjectVector = PyObjectArray{1}
const PyObjectMatrix = PyObjectArray{2}
export PyObjectVector, PyObjectMatrix, PyObjectArray
PyObjectArray{N}(undef::UndefInitializer, dims::Vararg{Integer,N}) where {N} =
PyObjectArray(undef, dims)
PyObjectArray(undef::UndefInitializer, dims::NTuple{N,Integer}) where {N} =
PyObjectArray{N}(undef, dims)
PyObjectArray(undef::UndefInitializer, dims::Vararg{Integer,N}) where {N} =
PyObjectArray{N}(undef, dims)
PyObjectArray{N}(x::AbstractArray{T,N}) where {T,N} =
copyto!(PyObjectArray{N}(undef, size(x)), x)
PyObjectArray(x::AbstractArray{T,N}) where {T,N} = PyObjectArray{N}(x)
function pyobjectarray_finalizer(x::PyObjectArray)
if C.CTX.is_initialized
if C.PyGILState_Check() == 1
# if this thread holds the GIL then decref now
for ptr in x.ptrs
C.Py_DecRef(ptr)
end
else
# otherwise re-attach the finalizer and try again next GC
finalizer(pyobjectarray_finalizer, x)
end
end
nothing
end
Base.IndexStyle(x::PyObjectArray) = Base.IndexStyle(x.ptrs)
Base.length(x::PyObjectArray) = length(x.ptrs)
Base.size(x::PyObjectArray) = size(x.ptrs)
@propagate_inbounds function Base.isassigned(x::PyObjectArray, i::Vararg{Integer})
@boundscheck checkbounds(Bool, x, i...) || return false
return @inbounds x.ptrs[i...] != C_NULL
end
@propagate_inbounds function Base.getindex(x::PyObjectArray, i::Integer...)
@boundscheck checkbounds(x, i...)
@inbounds ptr = x.ptrs[i...]
ptr == C_NULL && throw(UndefRefError())
return pynew(incref(ptr))
end
@propagate_inbounds function Base.setindex!(x::PyObjectArray, v, i::Integer...)
@boundscheck checkbounds(x, i...)
v_ = Py(v)
@inbounds decref(x.ptrs[i...])
@inbounds x.ptrs[i...] = incref(getptr(v_))
return x
end
@propagate_inbounds function Base.deleteat!(x::PyObjectVector, i::Integer)
@boundscheck checkbounds(x, i)
@inbounds decref(x.ptrs[i])
deleteat!(x.ptrs, i)
return x
end
function pyjlarray_array_interface(x::PyObjectArray)
return pydict(
shape = size(x),
typestr = "|O",
data = (UInt(pointer(x.ptrs)), false),
strides = strides(x.ptrs) .* sizeof(C.PyPtr),
version = 3,
)
end
# C._pyjlarray_get_buffer(o, buf, flags, x::PyObjectArray) = C.pyjl_get_buffer_impl(
# o,
# buf,
# flags,
# pointer(x.ptrs),
# sizeof(CPyPtr),
# length(x),
# ndims(x),
# "O",
# size(x),
# strides(x.ptrs) .* sizeof(CPyPtr),
# true,
# )