How to get a pointer Ptr{T} that references a variable of type T

I need to pass a Ptr{T} to a C function but pointer_from_objref returns Ptr{Void} rather than Ptr{T}… How should I do this?

In the following example, I need to pass a value of type Ptr{Foo} to the C function:

julia> struct Foo x end

julia> f = Foo(1)
Foo(1)

julia> pointer_from_objref(f)
Ptr{Void} @0x00007feff06d2ab0
2 Likes

I found a solution… but is it the best way?

julia> convert(Ptr{Foo}, pointer_from_objref(f))
Ptr{Foo} @0x00007f2c94e27ad0
2 Likes

If I’m not mistaken, you can also just tell ccall that the argument type is a Ptr{Void}.

Yes, Ptr{Void} works. Thanks

pointer_from_objref is not right and is in fact removed for immutable objects in 0.7. Just wrap it in a Ref.

Ref doesn’t really work for me. I have over a thousand ccall functions generated from Clang. The method signatures contain arguments that take pointers as well as returning results as pointers. I have demonstrated the problem with a MWE here.

Basically, the wrapper functions may accept Ptr{T} arguments and so I will need to call it with a pointer to the object. The pointer_from_objref function works very well except that it loses its type. The Ref function works only if it’s used inside the wrapper function, for which I would rather not do as I would have a thousand calls to edit (or mess with Clang, which would not be a very pleasant exercise.)

If I call the wrapper function with Ref(x), it could not dispatch to the wrapper function since it expects Ptr{T}. If I change the method signature to accept a RefValue{T}) type, then method dispatch works but the ccall crashes julia.

And that is it completely unsafe and can crash at any point when you put those ccalls inside a function (and is hence an error on julia 0.7). See Dissallow pointer_from_objref on immutable values · Issue #15857 · JuliaLang/julia · GitHub.

That was a Clang.jl bug Generating safer wrapper for pointer arguments · Issue #152 · JuliaInterop/Clang.jl · GitHub. Please regenerate your wrapper.

That’s interesting! However, the latest version of Clang still generates bad signature for me. Apparently, it does not recognize a typedef that is a pointer to a struct.

Consider this simple function:

typedef struct {
    double x;
} FOO, *FOOP;

FOOP test1(double a, double b, FOOP c);

It gets wrapped as

function test1(a::Cdouble, b::Cdouble, c::FOOP)
    ccall((:test1, test), FOOP, (Cdouble, Cdouble, FOOP), a, b, c)
end

But, it would be fine with Foo * instead:

typedef struct {
    double x;
} FOO, *FOOP;

FOO *test1(double a, double b, FOO *c);

turns into

function test1(a::Cdouble, b::Cdouble, c)
    ccall((:test1, test2), Ptr{FOO}, (Cdouble, Cdouble, Ptr{FOO}), a, b, c)
end

I’ll submit an issue to Clang project for this similar bug.

Since the problem only happens at the signature, I can work around the issue by doing a global search and replace of ::T with an empty string. So the end result isn’t too bad.

Thanks for your help.