# Testing and Validating the Strided Array Interface

**URL:** <https://discourse.julialang.org/t/testing-and-validating-the-strided-array-interface/135083>\
**Category:** Internals & Design\
**Tags:** proposal, strided-array\
**Created:** [January 15, 2026, 5:55pm UTC](https://discourse.julialang.org/t/testing-and-validating-the-strided-array-interface/135083 "2026-01-15T17:55:43Z")\
**Posts on this page:** 7\
**Page:** 1

<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 15, 2026, 5:55pm UTC](https://discourse.julialang.org/t/testing-and-validating-the-strided-array-interface/135083/1 "2026-01-15T17:55:43Z")

</div>

The strided array interface is documented in [Interfaces · The Julia Language](https://docs.julialang.org/en/v1/manual/interfaces/#man-interface-strided-arrays)

New `AbstractArray` subtypes can implement this interface to enable fast BLAS, LAPACK, IO, and Python interop methods. In addition, we would like some wrappers and views of strided arrays to be strided arrays as well.

However, due to bugs and unclear documentation, this composability often fails in practice. For example,  
[https://github.com/JuliaPy/PythonCall.jl/issues/579](https://github.com/JuliaPy/PythonCall.jl/issues/579) and [https://github.com/JuliaLang/julia/pull/60533](https://github.com/JuliaLang/julia/pull/60533)

I propose adding a function to Test, an exported syntax sugar function to Base, and two optional functions to the strided array interface, in order to help test if an array has a valid implementation of the strided array interface. I’m looking for feedback on these new functions.

## `Test.test_strided_interface(a::AbstractArray)`

If `isbitstype(eltype(a))` and `has_strided_get(a)`, iterate through the array checking that elements obtained through the strided interface match elements obtained using `getindex`.

If `isbitstype(eltype(a))` and `has_strided_set(a)`, iterate through the array setting elements with the strided interface, and checking that elements match elements obtained using `getindex`.

## `Base.has_strided_get(a::AbstractArray)::Bool = false` and `Base.has_strided_set(a::AbstractArray)::Bool = false`

These two functions have fallback definitions that return `false` and would be specialized to return true for arrays that implement the strided array interface, for example:  
`has_strided_get(a::Array) = true` and `has_strided_set(a::Array) = true`

The fallback definition ensures backwards compatibility with existing array types.

## `strided_ptr(f, a::AbstractArray)`

This is a simple syntax sugar for the `cconvert`, `unsafe_convert`, and `GC.@preserve` block.  
The goal is to have a nice-to-use alternative to the easy-to-misuse `pointer` function.

```julia
function strided_ptr(f, a::AbstractArray{T})
    a_cconv = Base.cconvert(Ptr{T}, a)
    GC.@preserve a_cconv begin
        f(Base.unsafe_convert(Ptr{T}, a_cconv))
    end
end

```

---

<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:** [January 22, 2026, 7:36pm UTC](https://discourse.julialang.org/t/testing-and-validating-the-strided-array-interface/135083/2 "2026-01-22T19:36:19Z")

</div>

Should these be defined on instances of `AbstractArray` or subtypes of `AbstractArray`?

---

<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 22, 2026, 9:28pm UTC](https://discourse.julialang.org/t/testing-and-validating-the-strided-array-interface/135083/3 "2026-01-22T21:28:24Z")

</div>

I’m not sure. Using instances instead of types is more flexible. For example, in PythonCall.jl it seems like a `PyArray` may or may not be strided based on the value of the `.strided` field.

> <https://github.com/JuliaPy/PythonCall.jl/blob/be1634298ff27633bc3b4ce414526100bad2fe2c/src/Wrap/PyArray.jl#L632-L637>

---

<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:** [February 1, 2026, 4:46am UTC](https://discourse.julialang.org/t/testing-and-validating-the-strided-array-interface/135083/4 "2026-02-01T04:46:06Z")

</div>

I have a draft PR [New functions `has_strided_get` and `has_strided_set` by nhz2 · Pull Request #60894 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/pull/60894)  
The functions need to be defined on instances for the `ReshapedArray` and `ReinterpretArray` methods to work.

I also ended up putting the test functions in `test/testhelpers/StridedArrays.jl`.

---

<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:** [April 8, 2026, 6:11pm UTC](https://discourse.julialang.org/t/testing-and-validating-the-strided-array-interface/135083/5 "2026-04-08T18:11:39Z")

</div>

Looking for help reviewing [NFC: Add StridedArrays.jl testhelper by nhz2 · Pull Request #61250 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/pull/61250)

This PR doesn’t change any functionality, it just consolidates the tests into a test helper file.

I also found a previous attempt to improve the strided array interface that seems to have stalled due to lack of testing. [RFC: Make `strides` into a generic trait by andyferris · Pull Request #30432 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/pull/30432)

---

<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:** [July 8, 2026, 5:51pm UTC](https://discourse.julialang.org/t/testing-and-validating-the-strided-array-interface/135083/6 "2026-07-08T17:51:27Z")

</div>

In [Strided array traits - Pull Request #60964 - JuliaLang/julia - GitHub](https://github.com/JuliaLang/julia/pull/60964) I am trying a system of type trait functions. Multiple trait functions are needed to capture whether an array is strided at the type level because of the way the Reshape and Reinterpret array wrapper types work. The new specializable functions are:

1. `Base.is_strided(::Type{<:A})`: Return `true` to declare that the array type follows the strided array interface.
2. `Base.is_vec_strided(::Type{<:A})`: Return `true` to declare that the array additionally has evenly spaced elements in column-major order. Implies `Base.is_strided`.
3. `Base.is_contiguous(::Type{<:A})`: Return `true` to declare that the array additionally has the same memory layout as an `Array`. Implies `Base.is_vec_strided` and provides default `strides` and `Base.elsize` definitions.
4. `is_ptr_loadable(::Type{<:A})`: Return `true` to indicate the element pointer can be used to load elements.
5. `is_ptr_storable(::Type{<:A})`: Return `true` to indicate the element pointer can be used to store elements.

There are are two additional functions (`has_contiguous_layout` and `has_vec_strided_layout`) that should not be specialized because they only exist to handle the fact that all strided zero dim arrays are trivially `contiguous`, and all strided vectors are trivially `vec_strided`.

---

<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:** [July 9, 2026, 5:57pm UTC](https://discourse.julialang.org/t/testing-and-validating-the-strided-array-interface/135083/7 "2026-07-09T17:57:00Z")

</div>

Here is an example of the performance improvements we can get with a working strided array interface.

```julia
using ZipArchives, FixedSizeArrays, PythonCall, BenchmarkTools, Random
data = rand(Xoshiro(1234), UInt8, 300000000);
f_data = FixedSizeArray(copy(data));
py_data = PyArray(copy(data));
@btime zip_crc32($data)
@btime zip_crc32($f_data)
@btime zip_crc32($py_data)

```

Julia 1.12.6:

```julia-auto
70.287 ms (0 allocations: 0 bytes)
82.036 ms (3 allocations: 24.07 KiB)
147.411 ms (3 allocations: 24.07 KiB)

```

With the strided array interface:

[Implement strided array traits - Pull Request #777 - JuliaPy/PythonCall.jl - GitHub](https://github.com/JuliaPy/PythonCall.jl/pull/777) [Implement strided array traits - Pull Request #191 - JuliaArrays/FixedSizeArrays.jl - GitHub](https://github.com/JuliaArrays/FixedSizeArrays.jl/pull/191) and [Use try\_strides if available - Pull Request #106 - JuliaIO/ZipArchives.jl - GitHub](https://github.com/JuliaIO/ZipArchives.jl/pull/106)

```julia-auto
70.127 ms (0 allocations: 0 bytes)
71.035 ms (0 allocations: 0 bytes)
71.421 ms (0 allocations: 0 bytes)

```
