# Julia weird behavior with array passing between Julia and Python

**URL:** https://discourse.julialang.org/t/julia-weird-behavior-with-array-passing-between-julia-and-python/135005
**Category:** General Usage
**Tags:** question
**Created:** [January 12, 2026, 3:30pm UTC](https://discourse.julialang.org/t/julia-weird-behavior-with-array-passing-between-julia-and-python/135005 "2026-01-12T15:30:44Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![dmitry-kabanov](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dmitry-kabanov/32/52639_2.png) [@dmitry-kabanov](https://discourse.julialang.org/u/dmitry-kabanov)
#### Post date: [January 12, 2026, 3:30pm UTC](https://discourse.julialang.org/t/julia-weird-behavior-with-array-passing-between-julia-and-python/135005/1 "2026-01-12T15:30:44Z")

</div>

Hi,

I work on a project where users can use numerical solvers in a cross-language manner.

In this project, arrays are passed as pointers to the actual data and re-wrapped in different languages according to their shapes (that is, in Python a NumPy array is built, for Julia native array is built, so on). All this changes happen using Python C API and Julia C API, without using any packages for conversion.

Something has happened after upgrading from Julia 1.11.8 to 1.12.4, and arrays are not passed correctly anymore because the dimensions on the Julia size somehow are not set correctly.  
I mean, I have not changed anything in my code: this error occurs only due to the change in the used Julia version.

I change only the Julia version using `juliaup add ...` and `juliaup default ...` commands.  
Then I remove the built code completely (`make clean`) and build it again (`make debug`).

With Julia 1.11.8:

```julia-auto

```

ipdb\> p y.shape  
(1,)

```julia-auto
which is correct, as I am passing a 1D array with only one element.

With Julia 1.12.0:

```

ipdb\> p y.shape  
(135881294944352,)

```julia-auto
Running the second time, I get a different "shape": `(130044954482816,)`, which kinda gives me a hint that somehow the array structure has changed.

With julia 1.12.4:

```

ipdb\> p y.shape  
(127460310906272,)

```julia-auto
and next time it is again a random number: `(130742402242656,)`.

Could somebody explain me why this happens? My code is the same, I just recompile it.
Python is obviously also the same, C compiler as well. The only thing that changes here is Julia's version. I cannot see any changes in the changelog for Julia 1.12 that there were some changes in the array structure.

Thanks!
```

---

<div class="post-metadata">

### Author: ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)
#### Post date: [January 12, 2026, 4:25pm UTC](https://discourse.julialang.org/t/julia-weird-behavior-with-array-passing-between-julia-and-python/135005/2 "2026-01-12T16:25:51Z")

</div>

> [@dmitry-kabanov](#):
>
> using Python C API and Julia C API, without using any packages for conversion.
> 
> Something has happened after upgrading from Julia 1.11.8 to 1.12.4, and arrays are not passed correctly anymore because the dimensions on the Julia size somehow are not set correctly.

How exactly are you passing the array and its size? Are you looking at the Array `.size` field? How are you accessing that? Are you sure it’s an `Array`?

---

<div class="post-metadata">

### Author: ![dmitry-kabanov](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dmitry-kabanov/32/52639_2.png) [@dmitry-kabanov](https://discourse.julialang.org/u/dmitry-kabanov)
#### Post date: [January 12, 2026, 7:03pm UTC](https://discourse.julialang.org/t/julia-weird-behavior-with-array-passing-between-julia-and-python/135005/3 "2026-01-12T19:03:23Z")

</div>

This is how I pass a Julia array back to Python:

```julia-auto
module CallbackWrapper
export make_wrapper_over_c_callback

import SciMLBase

using OpenInterfaces: OIFArrayF64, OIF_ARRAY_C_CONTIGUOUS, OIF_ARRAY_F_CONTIGUOUS

function _oif_array_f64_pointer_from_array_f64(arr::AbstractArray{T,N}) where {T<:Float64,N}
    ndim = ndims(arr)
    dimensions = Base.unsafe_convert(Ptr{Clong}, collect(size(arr)))
    data = Base.unsafe_convert(Ptr{Float64}, arr)
    oif_arr = Ref(
        OIFArrayF64(
            ndim,
            dimensions,
            data,
            OIF_ARRAY_C_CONTIGUOUS | OIF_ARRAY_F_CONTIGUOUS,
        ),
    )
    return oif_arr
end

```

it seems to me that the error is that I convert `size(arr)` to `Ptr{Clong}`, although the definition of `OIFArrayF64` uses `Int64`:

```julia-auto
struct OIFArrayF64
    nd::Int32
    dimensions::Ptr{Int64}
    data::Ptr{Float64}
    flags::Int32
end

```

for `dimensions`. `Clong` probably resolves to 32-bit integers instead of 64-bit integers. I wonder, how it worked before at all 🙂 I’ll check it when I am back to the office tomorrow and report it here.

---

<div class="post-metadata">

### Author: ![sgaure](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sgaure/32/14779_2.png) [@sgaure](https://discourse.julialang.org/u/sgaure)
#### Post date: [January 12, 2026, 7:37pm UTC](https://discourse.julialang.org/t/julia-weird-behavior-with-array-passing-between-julia-and-python/135005/4 "2026-01-12T19:37:32Z")

</div>

> [@dmitry-kabanov](#):
>
> it seems to me that the error is that I convert `size(arr)` to `Ptr{Clong}`

> [@dmitry-kabanov](#):
>
> ```julia-auto
> function _oif_array_f64_pointer_from_array_f64(arr::AbstractArray{T,N}) where {T<:Float64,N}
> ndim = ndims(arr)
> dimensions = Base.unsafe_convert(Ptr{Clong}, collect(size(arr)))
> data = Base.unsafe_convert(Ptr{Float64}, arr)
> oif_arr = Ref(
> OIFArrayF64(
> ndim,
> dimensions,
> data,
> OIF_ARRAY_C_CONTIGUOUS | OIF_ARRAY_F_CONTIGUOUS,
> ),
> )
> return oif_arr
> end
> 
> ```
> 
> it seems to me that the error is that I convert `size(arr)` to `Ptr{Clong}`

That’s one thing, but it may work, depending on your cpu’s byte order. The other problem is that the output of `collect` is a `Vector` which is not referenced (a reference from a pointer doesn’t count), so it may easily happen that it’s freed by the garbage collector at any time. And possibly reused for something else. That may be the odd value you’re seeing.

---

<div class="post-metadata">

### Author: ![nhz2](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nhz2/32/44428_2.png) [@nhz2](https://discourse.julialang.org/u/nhz2)
#### Post date: [January 12, 2026, 7:43pm UTC](https://discourse.julialang.org/t/julia-weird-behavior-with-array-passing-between-julia-and-python/135005/5 "2026-01-12T19:43:40Z")

</div>

> [@dmitry-kabanov](#):
>
> ```julia-auto
> dimensions = Base.unsafe_convert(Ptr{Clong}, collect(size(arr)))
> data = Base.unsafe_convert(Ptr{Float64}, arr)
> 
> ```

Both of these are missing a call to `Base.cconvert`, and a `GC.@preserve` of the result of the call to `Base.cconvert`. I have a PR to try and clarify this in the docs

> <https://github.com/JuliaLang/julia/pull/60533>
>
> This PR also documents \`cconvert\` as part of the strided array interface because… it may be needed if the default \`cconvert\` cannot work.
> 
> Here is an example of the bug this change fixes, which is closely related to the bug in #59685
> 
> \`\`\`julia
> struct MyVec \<: AbstractVector{UInt8} end
> Base.size(::MyVec) = (8,)
> Base.getindex(::MyVec, i::Int) = UInt8(i)
> struct MyWrapper x::UInt64 end
> Base.cconvert(::Type{Ptr{UInt8}}, ::MyVec) = Base.cconvert(Ref{MyWrapper}, MyWrapper(htol(0x0807060504030201)))
> Base.unsafe\_convert(::Type{Ptr{UInt8}}, x::Ref{MyWrapper}) = Ptr{UInt8}(Base.unsafe\_convert(Ref{MyWrapper}, x))
> Base.elsize(::Type{MyVec}) = 1
> Base.strides(::MyVec) = (1,)
> function has\_4(v)
> r = @ccall memchr(v::Ptr{UInt8}, 0x04::Cint, length(v)::Csize\_t)::Ptr{Nothing}
> r !== C\_NULL
> end
> has\_4(MyVec())
> \# true
> has\_4(view(MyVec(), 2:5))
> \# false
> \`\`\`
