Clang.jl
Clang.jl copied to clipboard
Add support for automatically calling unsafe_load() in getproperty()
Copying the description from the code:
By default the getproperty!(x::Ptr, ::Symbol) methods created for wrapped types will return pointers (Ptr{T}) to the struct fields. That behaviour is useful for accessing nested struct fields but it does require explicitly calling unsafe_load() every time. When enabled this option will automatically call unsafe_load() for you except on nested struct fields and arrays, which should make explicitly calling unsafe_load() unnecessary in most cases.
Here's the generated code for the struct-properties.h
header in the tests:
using CEnum: CEnum, @cenum [75/97867]
struct TypedefStruct
i::Cint
end
struct Other
i::Cint
end
function _getptr(x::Ptr{Other}, f::Symbol)
f === :i && return Ptr{Cint}(x + 0)
error("Unrecognized field of type `Other`" * ": $(f)")
end
function Base.getproperty(x::Ptr{Other}, f::Symbol)
f === :i && return unsafe_load(_getptr(x, f))
return getfield(x, f)
end
function Base.setproperty!(x::Ptr{Other}, f::Symbol, v)
unsafe_store!(_getptr(x, f), v)
end
mutable struct WithFields
int_value::Cint
int_ptr::Ptr{Cint}
struct_value::Other
struct_ptr::Ptr{Other}
typedef_struct_value::TypedefStruct
array::NTuple{2, Cint}
end
function _getptr(x::Ptr{WithFields}, f::Symbol)
f === :int_value && return Ptr{Cint}(x + 0)
f === :int_ptr && return Ptr{Ptr{Cint}}(x + 8)
f === :struct_value && return Ptr{Other}(x + 16)
f === :struct_ptr && return Ptr{Ptr{Other}}(x + 24)
f === :typedef_struct_value && return Ptr{TypedefStruct}(x + 32)
f === :array && return Ptr{NTuple{2, Cint}}(x + 36)
error("Unrecognized field of type `WithFields`" * ": $(f)")
end
function Base.getproperty(x::Ptr{WithFields}, f::Symbol)
f === :int_value && return unsafe_load(_getptr(x, f))
f === :int_ptr && return unsafe_load(_getptr(x, f))
f === :struct_value && return _getptr(x, f)
f === :struct_ptr && return unsafe_load(_getptr(x, f))
f === :typedef_struct_value && return _getptr(x, f)
f === :array && return _getptr(x, f)
return getfield(x, f)
end
function Base.setproperty!(x::Ptr{WithFields}, f::Symbol, v)
unsafe_store!(_getptr(x, f), v)
end
I've also tested it with CImGui.jl: https://github.com/Gnimuc/CImGui.jl/pull/131 I will admit the code is a bit hairy :octopus: Not sure if it's the cleanest implementation.
EDIT: marked as a draft because JET.jl found some issues with it.