# Seeking clarification on Ptr vs Ref in ccall

**URL:** <https://discourse.julialang.org/t/seeking-clarification-on-ptr-vs-ref-in-ccall/96883>\
**Category:** General Usage\
**Tags:** ccall\
**Created:** [March 31, 2023, 8:19am UTC](https://discourse.julialang.org/t/seeking-clarification-on-ptr-vs-ref-in-ccall/96883 "2023-03-31T08:19:28Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![jishnub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jishnub/32/33620_2.png) [@jishnub](https://discourse.julialang.org/u/jishnub)\
**Post date:** [March 31, 2023, 8:19am UTC](https://discourse.julialang.org/t/seeking-clarification-on-ptr-vs-ref-in-ccall/96883/1 "2023-03-31T08:19:28Z")

</div>

Suppose I have a C code

```julia
int sum(int *a, int n){
	int s = 0;
	for(int i=0; i<n; i++){
		s += a[i];
	}
	return s;
}

```

and I can call this from Julia as

```julia
julia> ccall((:sum, "./libsum.so"), Cint, (Ref{Cint},Cint), Cint[1,2,3], 3)
6

julia> ccall((:sum, "./libsum.so"), Cint, (Ptr{Cint},Cint), Cint[1,2,3], 3)
6

```

which of these two is the recommended form? The section [Calling C and Fortran Code · The Julia Language](https://docs.julialang.org/en/v1/manual/calling-c-and-fortran-code/#When-to-use-T,-Ptr%7BT%7D-and-Ref%7BT%7D) suggests

> For C code accepting pointers, [`Ref{T}`](https://docs.julialang.org/en/v1/base/c/#Core.Ref) should generally be used for the types of input arguments

but I have come across many libraries using `Ptr{T}` as the argument type, with seemingly no difference in the outcome. My limited (And somewhat naive) understanding of this is that `Ref{T}` ensures that the GC doesn’t clear the underlying memory, whereas `Ptr{T}` offers no such guarantee. This would suggest that `Ref{T}` is the safer option.

Could someone suggest the correct form here? And is there a reason to prefer `Ptr` over `Ref` in certain scenarios?

---

<div class="post-metadata">

**Author:** ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)\
**Post date:** [March 31, 2023, 10:17am UTC](https://discourse.julialang.org/t/seeking-clarification-on-ptr-vs-ref-in-ccall/96883/2 "2023-03-31T10:17:42Z")

</div>

If the memory is managed by Julia, `Ref` is preferred.

The actual difference is that `Base.cconvert` will convert to a `Base.RefArray` before converting to a pointer.

```julia
julia> Base.cconvert(Ref{Cint}, Cint[1,2,3])
Base.RefArray{Int32, Vector{Int32}, Nothing}(Int32[1, 2, 3], 1, nothing)

julia> Base.cconvert(Ptr{Cint}, Cint[1,2,3])
3-element Vector{Int32}:
 1
 2
 3

```

---

<div class="post-metadata">

**Author:** ![jishnub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jishnub/32/33620_2.png) [@jishnub](https://discourse.julialang.org/u/jishnub)\
**Post date:** [March 31, 2023, 10:41am UTC](https://discourse.julialang.org/t/seeking-clarification-on-ptr-vs-ref-in-ccall/96883/3 "2023-03-31T10:41:08Z")

</div>

In [Initialize buffer for ccall - #2 by stevengj](https://discourse.julialang.org/t/initialize-buffer-for-ccall/52659/2), the suggestion seems to be to use `Ptr`. Would it be more correct to pass a `Ref` in this instance?

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [March 31, 2023, 12:17pm UTC](https://discourse.julialang.org/t/seeking-clarification-on-ptr-vs-ref-in-ccall/96883/4 "2023-03-31T12:17:47Z")

</div>

> [@jishnub](#):
>
> Could someone suggest the correct form here? And is there a reason to prefer `Ptr` over `Ref` in certain scenarios?

If you have an `Array` object that you are passing, then `Ptr` and `Ref` will have essentially the same effect. If you _don’t_ have an `Array` already, then `Ref{T}` allows you to pass a `T` object and it will create the `Ref` for you. You need to explicitly create an `arg = Ref{T}()` object if you want to inspect the value of `arg[]` after the call, but this is potentially cheaper than allocating an `Array`.

Semantically, a `Ref{T}` object acts like a zero-dimensional container of length 1 in Julia, so I think it’s clearer to use it in `ccall` only if the argument is used as a pointer to a _single_ value, not a whole array. That’s really what `Ref` was designed for historically in Julia (it came long after `Ptr`).

So, in your `sum` function I would tend to pass `a` as `Ptr{Cint}` for a pointer to an arbitrary-length array. However, if you also passed a pointer to the _result_ (= 1 number), I would use `Ref` for that argument. That is, if your C function looked like:

```c
void sum(int *result, const int *array, int n) {
    /* ... store sum of array[i] values in *result ... */
}

```

then I would call it as:

```julia
a = Cint[1,2,3]
result = Ref{Cint}()
@ccall libsum.sum(result::Ref{Cint}, a::Ptr{Cint}, length(a)::Cint)::Cvoid
sum = result[]

```

> [@mkitti](#):
>
> The actual difference is that `Base.cconvert` will convert to a `Base.RefArray` before converting to a pointer.

Semantically, a `RefArray` acts like a 0-dimensional view of a _single_ element, and can be used to reference an arbitrary element of an array:

```julia
julia> a = [3,1,4]
3-element Vector{Int64}:
 3
 1
 4

julia> r = Ref(a, 3)
Base.RefArray{Int64, Vector{Int64}, Nothing}([3, 1, 4], 3, nothing)

julia> r[]
4

julia> length(r)
1

julia> ndims(r)
0

```

and I would tend to use it in that context (for passing pointers to individual elements, not the whole array).

---

<div class="post-metadata">

**Author:** ![jishnub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jishnub/32/33620_2.png) [@jishnub](https://discourse.julialang.org/u/jishnub)\
**Post date:** [March 31, 2023, 12:21pm UTC](https://discourse.julialang.org/t/seeking-clarification-on-ptr-vs-ref-in-ccall/96883/5 "2023-03-31T12:21:22Z")

</div>

Thanks, that’s helpful. Does that mean the documentation stating

> For C code accepting pointers, `Ref{T}` should generally be used for the types of input arguments

may clarify that this is unnecessary for julia arrays, and a `Ptr` may be passed instead? Tbh the documentation is quite vague on this, and a few examples suggesting the canonical use cases would be quite helpful.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [March 31, 2023, 12:23pm UTC](https://discourse.julialang.org/t/seeking-clarification-on-ptr-vs-ref-in-ccall/96883/6 "2023-03-31T12:23:21Z")

</div>

> [@jishnub](#):
>
> may clarify that this is unnecessary for julia arrays, and a `Ptr` may be passed instead?

Yes, I think that should be clarified.

---

<div class="post-metadata">

**Author:** ![stephancb](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stephancb/32/14243_2.png) [@stephancb](https://discourse.julialang.org/u/stephancb)\
**Post date:** [March 31, 2023, 4:47pm UTC](https://discourse.julialang.org/t/seeking-clarification-on-ptr-vs-ref-in-ccall/96883/7 "2023-03-31T16:47:03Z")

</div>

Sorry for the slight high-jacking, but also in section [Calling C and Fortran Code · The Julia Language](https://docs.julialang.org/en/v1/manual/calling-c-and-fortran-code/#When-to-use-T,-Ptr%7BT%7D-and-Ref%7BT%7D) this first was cryptic for me:

`When calling Fortran, all inputs must be passed by pointers to heap- or stack-allocated values, so all type correspondences above should contain an additional `Ptr{…}`or`Ref{…}` wrapper around their type specification.`

After trial and error my conclusion was that in Fortran all arguments, even scalar ones, need to be passed as `Ptr{..}` or `Ref{..}`, same as `sum` in the C example above, and even so when the argument is `intent(in)`. They also need to be initialized as `Ref(...)`. Example:

a = Cint[1,2,3]  
result = Ref(Cint(0))  
len = Ref(Cint(length(a)))  
@ccall libfortransum.sum(result::Ref{Cint}, a::Ptr{Cint}, len::Ref{Cint})::Cvoid  
sum = result

Especially for Fortran I think that perhaps it should be clarified that a “wrapper” in the actual `ccall` is not sufficient. All scalars, whether input or output, must be initialized as `Ref`s, and there `Ptr` does not work.

---

<div class="post-metadata">

**Author:** ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)\
**Post date:** [March 31, 2023, 4:52pm UTC](https://discourse.julialang.org/t/seeking-clarification-on-ptr-vs-ref-in-ccall/96883/8 "2023-03-31T16:52:09Z")

</div>

After `Base.cconvert`, `Base.unsafe_convert` would then convert the `Base.RefArray` to a `Ptr`:

```julia
$ julia
               _
   _ _ _(_)_ | Documentation: https://docs.julialang.org
  (_) | (_) (_) |
   _ _ _| |_ __ _ | Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` | |
  | | |_| | | | (_| | | Version 1.9.0-beta3 (2023-01-18)
 _/ |\ __'_|_|_|\__'_| | Official https://julialang.org/ release
|__/ |

julia> Base.cconvert(Ref{Cint}, Cint[1,2,3])
Base.RefArray{Int32, Vector{Int32}, Nothing}(Int32[1, 2, 3], 1, nothing)

julia> Base.unsafe_convert(Ref{Cint}, Base.cconvert(Ref{Cint}, Cint[1,2,3]))
Ptr{Int32} @0x00007fbb60190860

julia> Base.cconvert(Ref{Cint}, Cint[1,2,3])
Base.RefArray{Int32, Vector{Int32}, Nothing}(Int32[1, 2, 3], 1, nothing)

julia> @which Base.cconvert(Ref{Cint}, Cint[1,2,3])
cconvert(T::Type, x)
     @ Base essentials.jl:492

julia> @which Base.convert(Ref{Cint}, Cint[1,2,3])
convert(::Type{Ref{T}}, x::AbstractArray{T}) where T
     @ Base refpointer.jl:117

julia> @which Base.unsafe_convert(Ref{Cint}, Base.cconvert(Ref{Cint}, Cint[1,2,3]))
unsafe_convert(::Type{Ref{T}}, x::Ref{T}) where T
     @ Base refpointer.jl:101

```

For `Array`, perhaps it does not matter. Might it matter for other kinds of `AbstractArray`?

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [March 31, 2023, 5:03pm UTC](https://discourse.julialang.org/t/seeking-clarification-on-ptr-vs-ref-in-ccall/96883/9 "2023-03-31T17:03:01Z")

</div>

> [@mkitti](#):
>
> For `Array`, perhaps it does not matter. Might it matter for other kinds of `AbstractArray`?

No, I don’t think so.

In any case where you need a C-compatible pointer to multiple elements, not just one, then `allocatedinline(T)` must be true and it [just calls `pointer(array, i)`](https://github.com/JuliaLang/julia/blob/8b19f5fa276b738034cdc26c13cc9f38ba1ea362/base/refpointer.jl#L120-L121), which in turn just [calls `unsafe_convert(Ptr{T}, array)`](https://github.com/JuliaLang/julia/blob/8b19f5fa276b738034cdc26c13cc9f38ba1ea362/base/abstractarray.jl#L1246). So in the end it should be equivalent to `Ptr{T}`.

---

<div class="post-metadata">

**Author:** ![ajinkya-k](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ajinkya-k/32/213627_2.png) [@ajinkya-k](https://discourse.julialang.org/u/ajinkya-k)\
**Post date:** [January 15, 2025, 6:01pm UTC](https://discourse.julialang.org/t/seeking-clarification-on-ptr-vs-ref-in-ccall/96883/10 "2025-01-15T18:01:59Z")

</div>

> [@stevengj](#):
>
> Yes, I think that should be clarified.

Hello! Sorry to resurrect this thread, buy I had the exact same question and I was wondering if there still is any interest in clarifying the documentation. I skimmed the 1.12-dev version docs and this does not seem to have been clarified yet.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [January 15, 2025, 11:46pm UTC](https://discourse.julialang.org/t/seeking-clarification-on-ptr-vs-ref-in-ccall/96883/11 "2025-01-15T23:46:14Z")

</div>

> [@ajinkya-k](#):
>
> I was wondering if there still is any interest in clarifying the documentation. I skimmed the 1.12-dev version docs and this does not seem to have been clarified yet.

Please feel free to submit a PR to the docs.

---

<div class="post-metadata">

**Author:** ![ajinkya-k](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ajinkya-k/32/213627_2.png) [@ajinkya-k](https://discourse.julialang.org/u/ajinkya-k)\
**Post date:** [January 16, 2025, 12:42am UTC](https://discourse.julialang.org/t/seeking-clarification-on-ptr-vs-ref-in-ccall/96883/12 "2025-01-16T00:42:39Z")

</div>

I’m not sure I’m knowledgeable enough to do it though I can take a stab at it
