Yes, this is the pycall approach. If this is an struct that you need to operate on directly, you can make a struct with an extra field that holds the reference to the julia object (i.e. give it three field with the third one being an Any).
No this is wrong. This will not keep the julia array live. Julia is free to disgard the ar
field.
It seems that you only need to use this struct when passing stuff to C so in that case, you can simply create that struct at ccall
callsite within cconvert/unsafe_convert. You can put all allocations into cconvert(::Type{Ptr{Bar}}, ::Vector{Float64})
, and cconvert(::Type{Ptr{Bar}}, ::Float64)
including allocation of a Ref{Bar}
and return the Ref{Bar}
in unsafe_convert
. The ccall
lowering will guarantee that the unsafe operatioins in unsafe_convert
are safe assuming all the objects that needs to be alive are in the return value of cconvert
.
Base.cconvert(::Type{Ptr{Bar}}, v::Float64) = Ref(Bar(v)) # This use the `::Float64` constructor
function Base.cconvert(::Type{Ptr{Bar}}, vv::Vector{Float64}) # This replaces the `::Vector{Float64}` constructor
ar = Bar.(vv)
bar = Bar(reinterpret(UInt64, pointer(ar)), 0x01)
return (Ref(bar), ar)
end
function Base.unsafe_convert(::Type{Ptr{Bar}}, t::Tuple{Ref{Bar},Vector{Bar}})
return pointer_from_objref(t[1])
end