I was just recently trying to use the wrap-a-pointer-to-an-immutable-in-a-1-element-array trick while wrapping some library code where some important setter functions were unfortunately only defined as inline in the headers.
I defined my own setters by assigning to the immutable in the array. The code seemed to work as expected, except that, after one or two calls, I'd get a somewhat cryptic stacktrace and julia would dump core. I got the impression that this was being triggered by a GC sweep. I believe I correctly associated the library's deleter for this pointer with the array's finalizer (actually, for the object that owned the array), so this failure caused me to doubt whether this setter hack was valid, but this thread suggests it might be OK. Can we confirm that? If so, I might spend more time looking for the bug in my code. On Thu, Feb 26, 2015 at 4:27 PM, Jameson Nash <[email protected]> wrote: > You need to make new versions of both immutable objects, recursively > constructing the updated struct, then unsafe_store it back to the original > C location > > On Thu, Feb 26, 2015 at 2:32 PM J Luis <[email protected]> wrote: > >> >> Yes you warned me that it may sometimes segv, but what else can I do to >>>> get the pointer to a variable (a scalar or a composite type)? >>>> I asked it once in https://groups.google.com/forum/?fromgroups=#!topic/ >>>> julia-users/i8DO3pBAHPU and my safe was to box it in pointer([M]). >>>> What else should I have done? >>>> >>> You can’t get a pointer to it, because an immutable doesn’t have a >>> memory location associated with it. What you can do is create a new >>> immutable with the values from the old immutable, plus any modifications >>> you wanted to make. >>> >> OK, I think I had understood that but I'm not finding a way to do it in >> my case. The point is what I need to replace is not the content of >> something pointed by a pointer. Instead it's (for example) the contents of >> the member 'rgb_low' which in itself is another immutable >> >> https://github.com/joa-quim/GMT.jl/blob/master/src/libgmt_h.jl#L1486 >> >> no problems is creating a new 'Array_4_Cdouble' but how do I put in >> rgb_low, that is an immutable and for which I have no pointer? (that's >> why I was chasing the pointers of the member's type) >> >> Thanks >> >> >>> >>>> To send in a pointer to an integer to C that wants for example >>>> >>>> function blabla(int *n) {} >>>> >>>> what I do is >>>> >>>> n = [0] >>>> (wrapper to blabla) blabla(pointer(n)) >>>> n = unsafe_ref(n) >>>> >>>> How should I proceed here instead of using pointer([n])? >>>> >>> This usage is fine. You are calling pointer(n) here (not pointer([n])), >>> and you keep the variable n around until all uses of it are finished >>> (inside of blabla). >>> >>> >>>> The link you send me https://github.com/JuliaLang/ >>>> julia/blob/jn/ccall3/doc/manual/calling-c-and-fortran- >>>> code.rst#passing-pointers-for-modifying-inputs >>>> >>>> gives as example "width = Ref{Cint}(0)" but that errors >>>> >>>> julia> width = Ref{Cint}(0) >>>> ERROR: UndefVarError: Ref not defined >>>> >>>> This will only work on Julia 0.4 after that pull-request is merged. On >>> 0.3, you can use an Array{Cint,0} to achieve a similar effect. >>> >>> I'm more than happy to follow your advice but I need an alternative. >>>> >>>> Thanks >>>> >>>> Joaquim >>>> >>>> >>>>> >>>>> >>>>> On Tue, Feb 24, 2015 at 11:36 AM J Luis <[email protected]> wrote: >>>>> >>>>>> >>>>>> >>>>>> use unsafe_load() to convert the value to a julia object, then >>>>>>> unsafe_store() to write the new struct back. >>>>>>> >>>>>>> at some point, I want to modify unsafe_load/unsafe_store to take a >>>>>>> fieldname symbol as the second argument to make this functionality more >>>>>>> direct available. however, there hasn't seemed to be a request / issue >>>>>>> open >>>>>>> for it yet. >>>>>>> >>>>>> >>>>>> PLEASE, do. >>>>>> >>>>>> I have the same type of problem but I'm not able to solve it with the >>>>>> solutions proposed in this thread. >>>>>> See, I have this and want to change the *rgb_low* >>>>>> >>>>>> julia> gmt_lut = unsafe_load(C.range, 1); >>>>>> >>>>>> julia> gmt_lut.rgb_low >>>>>> GMT.Array_4_Cdouble(0.583333333333333,0.0,1.0,0.0) >>>>>> >>>>>> which is a >>>>>> >>>>>> immutable Array_4_Cdouble >>>>>> d1::Cdouble >>>>>> d2::Cdouble >>>>>> d3::Cdouble >>>>>> d4::Cdouble >>>>>> end >>>>>> >>>>>> so I do >>>>>> >>>>>> julia> z = GMT.Array_4_Cdouble(0.0, 0.0, 0.0, 0.0) >>>>>> GMT.Array_4_Cdouble(0.0,0.0,0.0,0.0) >>>>>> >>>>>> julia> unsafe_store!(pointer([gmt_lut.rgb_low]), z) >>>>>> Ptr{GMT.Array_4_Cdouble} @0x00000000819faf60 >>>>>> >>>>>> no errors but I don't know where new *z* immutable landed on because >>>>>> I keep seeing the old value >>>>>> >>>>>> julia> gmt_lut.rgb_low >>>>>> GMT.Array_4_Cdouble(0.583333333333333,0.0,1.0,0.0) >>>>>> >>>>>> I suspect part of it is dues to the pointer([gmt_lut.rgb_low]) command >>>>>> because when I do several of those on line I keep getting different >>>>>> addresses >>>>>> >>>>>> julia> pointer([gmt_lut.rgb_low]) >>>>>> Ptr{GMT.Array_4_Cdouble} @0x0000000082b7baf0 >>>>>> >>>>>> julia> pointer([gmt_lut.rgb_low]) >>>>>> Ptr{GMT.Array_4_Cdouble} @0x0000000082ba00d0 >>>>>> >>>>>> julia> pointer([gmt_lut.rgb_low]) >>>>>> Ptr{GMT.Array_4_Cdouble} @0x0000000082ba0670 >>>>>> >>>>>> but than how can modify this field(s)? >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>> >>> >>
