JuliaInterop / Clang.jl

C binding generator and Julia interface to libclang
https://juliainterop.github.io/Clang.jl/
MIT License
219 stars 68 forks source link

Using `fieldnames` (and similar) for wrapped C `union`s #426

Open JoshuaLampert opened 1 year ago

JoshuaLampert commented 1 year ago

Currently, C unions and structs containing a union are wrapped as a julia struct having one field data with overwritten Base.getproperty and Base.setproperty! functions, e.g.

union testunion
{
    int y;
};

struct teststruct
{
  int x;
  union testunion p;
};

is wrapped as

using CEnum

struct testunion
    data::NTuple{4, UInt8}
end

function Base.getproperty(x::Ptr{testunion}, f::Symbol)
    f === :y && return Ptr{Cint}(x + 0)
    return getfield(x, f)
end

function Base.getproperty(x::testunion, f::Symbol)
    r = Ref{testunion}(x)
    ptr = Base.unsafe_convert(Ptr{testunion}, r)
    fptr = getproperty(ptr, f)
    GC.@preserve r unsafe_load(fptr)
end

function Base.setproperty!(x::Ptr{testunion}, f::Symbol, v)
    unsafe_store!(getproperty(x, f), v)
end

struct teststruct
    data::NTuple{8, UInt8}
end

function Base.getproperty(x::Ptr{teststruct}, f::Symbol)
    f === :x && return Ptr{Cint}(x + 0)
    f === :p && return Ptr{testunion}(x + 4)
    return getfield(x, f)
end

function Base.getproperty(x::teststruct, f::Symbol)
    r = Ref{teststruct}(x)
    ptr = Base.unsafe_convert(Ptr{teststruct}, r)
    fptr = getproperty(ptr, f)
    GC.@preserve r unsafe_load(fptr)
end

function Base.setproperty!(x::Ptr{teststruct}, f::Symbol, v)
    unsafe_store!(getproperty(x, f), v)
end

This doesn' t allow to properly use fieldnames or propertynames (and similar functions) as they return (:data,) (or similar) and not the actual fields you can access by getproperty. The problem came up in https://github.com/trixi-framework/P4est.jl/issues/72.

cc @ranocha, @sloede

Gnimuc commented 1 year ago

dup of #316?

thomvet commented 9 months ago

It isn't really the same issue? In #316 the autocomplete doesn't work for the Ptr{T} type, but it would work for struct T directly. In this issue, there is only the ":data" field in the struct. Way to the solution is probably quite different?