From f440164f7d90b50a33f2f5b4f1f4577ee2947b2a Mon Sep 17 00:00:00 2001 From: Joshua Lampert Date: Tue, 11 Apr 2023 19:49:46 +0200 Subject: [PATCH 1/2] allow setproperty! for PointerWrappers with special structs --- src/pointerwrappers.jl | 8 +++++--- test/tests_basic.jl | 14 ++++++++++++-- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/pointerwrappers.jl b/src/pointerwrappers.jl index 3ee9457..1383ad9 100644 --- a/src/pointerwrappers.jl +++ b/src/pointerwrappers.jl @@ -70,10 +70,12 @@ end function Base.setproperty!(pw::PointerWrapper{T}, name::Symbol, v) where T i = findfirst(isequal(name), fieldnames(T)) if isnothing(i) - error("type $(string(T)) has no field $name") + # For some `struct`s, `fieldnames` gives `data` and not the actual field names, but we can use `Base.setproperty!` for pointers, + # see https://github.com/trixi-framework/P4est.jl/issues/72 and https://github.com/trixi-framework/P4est.jl/issues/79 + Base.setproperty!(pointer(pw), name, v) + else + unsafe_store!(reinterpret(Ptr{fieldtype(T, i)}, pointer(pw) + fieldoffset(T, i)), v) end - - unsafe_store!(reinterpret(Ptr{fieldtype(T, i)}, pointer(pw) + fieldoffset(T, i)), v) end # `[]` allows one to access the actual underlying data and diff --git a/test/tests_basic.jl b/test/tests_basic.jl index 0ec5a3f..fff81be 100644 --- a/test/tests_basic.jl +++ b/test/tests_basic.jl @@ -44,12 +44,22 @@ end ptr = Base.unsafe_convert(Ptr{MyStruct}, Ref(obj)) pw = PointerWrapper(ptr) @test pw.value[] == 0.0 - pw.value[] = 1.0 + @test_nowarn pw.value[] = 1.0 @test pw.value[] == 1.0 @test pw.value[1] == 1.0 - pw.value[1] = 2.0 + @test_nowarn pw.value[1] = 2.0 @test pw.value[1] == 2.0 @test pw.value[] == 2.0 + # using `setproperty!` + @test_nowarn pw.value = 3.0 + @test pw.value[1] == 3.0 + @test pw.value[] == 3.0 + # using `setproperty!` for special `struct`s + # see https://github.com/trixi-framework/P4est.jl/issues/72 and https://github.com/trixi-framework/P4est.jl/issues/79 + @test p4est_pw.global_first_position.level[] == 29 + @test_nowarn p4est_pw.global_first_position.level = 30 + @test p4est_pw.global_first_position.level[] == 30 + @test_nowarn p4est_pw.global_first_position.level = 29 # test if we can set the user_pointer p4est_pw.user_pointer = Ptr{Cvoid}(3) From 1483df31de8a9514610424d2dce3809ae9c53d4a Mon Sep 17 00:00:00 2001 From: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> Date: Tue, 11 Apr 2023 20:52:54 +0200 Subject: [PATCH 2/2] Update pointerwrappers.jl --- src/pointerwrappers.jl | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/pointerwrappers.jl b/src/pointerwrappers.jl index 1383ad9..57a15d7 100644 --- a/src/pointerwrappers.jl +++ b/src/pointerwrappers.jl @@ -72,10 +72,9 @@ function Base.setproperty!(pw::PointerWrapper{T}, name::Symbol, v) where T if isnothing(i) # For some `struct`s, `fieldnames` gives `data` and not the actual field names, but we can use `Base.setproperty!` for pointers, # see https://github.com/trixi-framework/P4est.jl/issues/72 and https://github.com/trixi-framework/P4est.jl/issues/79 - Base.setproperty!(pointer(pw), name, v) - else - unsafe_store!(reinterpret(Ptr{fieldtype(T, i)}, pointer(pw) + fieldoffset(T, i)), v) + return Base.setproperty!(pointer(pw), name, v) end + return unsafe_store!(reinterpret(Ptr{fieldtype(T, i)}, pointer(pw) + fieldoffset(T, i)), v) end # `[]` allows one to access the actual underlying data and