JuliaGL / ModernGL.jl

OpenGL 3+ bindings for Julia

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

is it a better choice to use Ref{} instead of Ptr{}?

Gnimuc opened this issue · comments

julia v0.4 is finally released, i find a major change about pointer is Ref{T}.
it says using Ref{T} is more safer

As a safer alternative to creating pointers (Ptr), the managed reference type Ref has been added. A Ref points to the data contained by a value in an abstract sense, and in a way that is GC-safe.

and

When passing a by-reference argument to ccall, you can declare the argument type to be Ref{T} instead of Ptr{T}, and just pass x instead of &x.

but it seems if we do not change those Ptr{T} argument types in glfunction.jl, one may face a problem when trying to use Ref{}. take a look at this example:

# test 1
bufferID = convert(GLuint, 0)
glGenBuffers(1, pointer_from_objref(bufferID))
@show bufferID

out => bufferID = 0x00000001    # ok

# test 2
bufferID = convert(GLuint, 0)
glGenBuffers(1, Ref(bufferID))
@show bufferID

out => bufferID = 0x00000000    # unexpected result

# test 3
bufferID = GLuint[0]
glGenBuffers(1, Ref(bufferID))
@show bufferID[]

out => bufferID[] = 0x00000001  # ok 

i know doing this will break some other repos(e.g. GLAbstraction.jl), i'm also not sure whether a C programmer will feel wired when using this syntax glGenBuffers(1, bufferID) which in C is glGenBuffers(1, &bufferID).

commented

test 2

that yields unexpected results because you use Ref wrong.
It should be:

bufferID = Ref{GLuint}(0)
glGenBuffers(1, bufferID)
@show bufferID[]

Ref(...) copies the value to another location, from what I know, so it won't mess with the immutable.

I've been thinking about this as well, but then I haven't had time to implement anything.
Since we use @generated functions, we can emit code specialized to the arguments.
So we could do something like this:

to_gl_args(::Type{Ptr{GLFloat}) = Ref{GLFloat}
#etc...
#in the @generated function
map(to_gl_args, gl_fun_arg_types)

thank you @SimonDanisch! i misunderstood the doc, i thought Ref is a one-to-one analogy to & in C/C++, which is not true. the doc about Ref() is still missing. i've stumbled over this problem for a couple of days. i even posted a question on stackoverflow, but no one gave a reply. i don't know @generated function stuff, it seems that both

bufferID = Ref{GLuint}(0)
glGenBuffers(1, bufferID)
@show bufferID[]

and

bufferID = 0
glGenBuffers(1, bufferID)
@show bufferID</strike>

would be OK if you reimplemented with @generated function.

you saved my day 👍 , thanks again!

EDIT: no, the second snippet won't work, it's the same as test 2.