Search code examples
c++cjuliavoid-pointers

Cast a variable to void pointer in Julia


In C/C++ we are able to do this:

double my_var = 4.32;
void* my_var_ptr = &my_var;

which results in the my_var_ptr being a void pointer pointing to the memory which stores the value 4.32.

I am trying to do the same in Julia, but I face several errors. Naively, I tried this:

my_var=Cdouble(4.32)
my_var_ptr=Ptr{Cvoid}(pointer(my_var))

which failed with the error: ERROR: MethodError: no method matching pointer(::Float64) The failure (I assume) is because I am trying to create a Cvoid pointer from Cdouble object.

Any solution on that?

Thanks in advance!


Solution

  • TL; DR

    julia> my_var = Cdouble(4.32)
    julia> my_var_ptr = Ptr{Cvoid}(pointer_from_objref(Ref(my_var)))
    Ptr{Nothing} @0x00007f2a9148c6c0
    

    pointer only works for array-like elements

    julia> methods(pointer)
    # 18 methods for generic function "pointer":
    [1] pointer(a::Random.UnsafeView) in Random at /usr/share/julia/stdlib/v1.7/Random/src/RNGs.jl:516
    [2] pointer(x::SuiteSparse.CHOLMOD.Sparse{Tv}) where Tv in SuiteSparse.CHOLMOD at /usr/share/julia/stdlib/v1.7/SuiteSparse/src/cholmod.jl:359
    [3] pointer(x::SuiteSparse.CHOLMOD.Dense{Tv}) where Tv in SuiteSparse.CHOLMOD at /usr/share/julia/stdlib/v1.7/SuiteSparse/src/cholmod.jl:358
    [4] pointer(x::SuiteSparse.CHOLMOD.Factor{Tv}) where Tv in SuiteSparse.CHOLMOD at /usr/share/julia/stdlib/v1.7/SuiteSparse/src/cholmod.jl:360
    [5] pointer(V::SubArray{T, N, P, I, true} where {T, N, P, I<:Union{Tuple{Vararg{Real}}, Tuple{AbstractUnitRange, Vararg{Any}}}}, i::Int64) in Base at subarray.jl:431
    [6] pointer(V::SubArray{T, N, P, I, true} where {T, N, P, I}, i::Int64) in Base at subarray.jl:430
    [7] pointer(V::SubArray{<:Any, <:Any, <:Array, <:Tuple{Vararg{Union{Int64, AbstractRange{Int64}}}}}, is::Base.AbstractCartesianIndex{N}) where N in Base at subarray.jl:433
    [8] pointer(V::SubArray{<:Any, <:Any, <:Array, <:Tuple{Vararg{Union{Int64, AbstractRange{Int64}}}}}, is::Tuple) in Base at deprecated.jl:212
    [9] pointer(A::PermutedDimsArray, i::Integer) in Base.PermutedDimsArrays at permuteddimsarray.jl:61
    [10] pointer(x::AbstractArray{T}) where T in Base at abstractarray.jl:1164
    [11] pointer(x::AbstractArray{T}, i::Integer) where T in Base at abstractarray.jl:1165
    [12] pointer(p::Cstring) in Base at c.jl:186
    [13] pointer(buffer::Base64.Buffer) in Base64 at /usr/share/julia/stdlib/v1.7/Base64/src/buffer.jl:20
    [14] pointer(x::SubString{String}) in Base at strings/substring.jl:122
    [15] pointer(x::SubString{String}, i::Integer) in Base at strings/substring.jl:123
    [16] pointer(p::Cwstring) in Base at c.jl:187
    [17] pointer(s::String) in Base at strings/string.jl:95
    [18] pointer(s::String, i::Integer) in Base at strings/string.jl:96
    

    However, you should check pointer_from_objref, for example:

    julia> pointer_from_objref(Ref(1))
    Ptr{Nothing} @0x00007f2a914feb60
    

    But from the wiki...

    Get the memory address of a Julia object as a Ptr. The existence of the resulting Ptr will not protect the object from garbage collection, so you must ensure that the object remains referenced for the whole time that the Ptr will be used.

    This function may not be called on immutable objects, since they do not have stable memory addresses.

    See also unsafe_pointer_from_objref.