2

I am using stb image library to load a image into C-style contiguous array. I want to move this array into a xtensor style xtensor or xarray with xt::adapt. Here is the demonstration code:

// It must be C-stype array because stb is C library.
std::size_t size = 24;
unsigned char arr_1d[size];
for (auto i = 0; i < size; ++i) {
  arr_1d[i] = i + 1;
}

// Convert 1D array with 24 elements into (3, 2, 4) xtensor.
auto img = xt::adapt(arr_1d, xt::xshape<3, 2, 4>(), xt::no_ownership());

But I kept getting the error:

test_xtensor.cpp:16:14: error: no matching function for call to 'adapt'
  auto img = xt::adapt(arr_1d, xt::xshape<3, 2, 4>(), xt::no_ownership());
             ^~~~~~~~~
/tmp/xtensor-install/include/xtensor/xadapt.hpp:85:5: note: candidate template ignored: substitution failure [with L = xt::layout_type::row_major]: variably modified type 'unsigned char (&)[size]' cannot be used as a template argument
    adapt(C&& container, const SC& shape, layout_type l = L)

Is it possible to achieve the above task with C-style array or I must convert to C++ vector first?

Lion Lai
  • 1,862
  • 2
  • 20
  • 41
  • 1
    looks like you don't need `xt::no_ownership()` for a stack allocated array https://xtensor.readthedocs.io/en/latest/adaptor.html#adapting-stack-allocated-arrays – Alan Birtles Mar 22 '23 at 08:28

1 Answers1

2

The following compiles:

auto img = xt::adapt((char *)arr_1d, xt::xshape<3, 2, 4>());

As I understand the documentation, it ought to work without the cast, but I get the following error about that candidate not being considered: (Clang 14 on macOS)

/opt/homebrew/include/xtensor/xadapt.hpp:458:17: note: candidate template ignored: could not match 'T[N]' against 'unsigned char[size]'
    inline auto adapt(T (&c_array)[N], const SC& shape, layout_type l = L)
Botje
  • 26,269
  • 3
  • 31
  • 41
  • I also think `xt::adapt(arr_1d, xt::xshape<3, 2, 4>());` should work because `arr_1d` is already the address of the first element of the array `arr_1d`. – Lion Lai Mar 22 '23 at 09:01
  • Yes, that is what the second part of my question states. "without the cast". – Botje Mar 22 '23 at 09:29
  • 2
    `cosntexpr std::size_t size=24;` will work. You are using a none standard extension called *VLA* right now. Making `size` a compile-time constant will remove the problem. – Red.Wave Mar 22 '23 at 11:42
  • Oh, well spotted! I did not connect the two. – Botje Mar 22 '23 at 12:26