title: Pass multidimensional array to extern "C" function as void *
body: <p>I have a C function in my library that works with multidimensional arrays nicely:</p>
  
  <pre><code>void    alx_local_maxima_u8 (ptrdiff_t rows, ptrdiff_t cols,
                      const uint8_t arr_in[static restrict rows][static cols],
                      bool arr_out[static restrict rows][static cols])
          __attribute__((nonnull));
  </code></pre>
  
  <p>And I have a <code>unsigned char *</code> that I receive from a <code>class</code> defined in openCV.  That pointer represents a bidimensional data, but it isn't, and I have to use it with pointer arithmetics (<code>unsigned char *img_pix = img-&gt;data + i*img-&gt;step + j;</code>), which I don't especially like.</p>
  
  <p>I create an array of <code>bool</code> of the same size of the image (this is a real array, so I can use array notation) to store the results of the function.</p>
  
  <p>I could write an almost exact copy of <code>alx_local_maxima_u8()</code> that uses just a pointer and pointer arithmetics, but I'd like to be able to re-use it if I can.</p>
  
  <p>Is it safe to write a prototype that uses a <code>void *</code> in this way just to fool C++?:</p>
  
  <pre><code>extern "C"
  {
  [[gnu::nonnull]]
  void    alx_local_maxima_u8 (ptrdiff_t rows, ptrdiff_t cols,
                               const void *arr_in,
                               void *arr_out);
  }
  </code></pre>
  
  <p>In theory <code>void *</code> can hold any pointer which is what C will receive, and C will not access any data that doesn't belong to those pointers, so the only problems I see are aliasing a <code>unsigned char *</code> as a <code>uint8_t *[]</code>,  and passing a <code>void *</code> where a <code>uint8_t *[]</code> is expected, which may cause all kind of linker errors.  Also, I don't know if C <code>bool</code> and C++ <code>bool</code> will translate into the same thing in memory (I hope so).</p>
  
  <p>Maybe I should write a wrapper in C which receives <code>void *</code> and passes them to the actual function, so that I don't need to fool C++.</p>
  
  <p>Performance IS a concern, but I use <code>-flto</code>, so any wrappers will probably vanish in the linker.</p>
  
  <p>I use GCC (<code>-std=gnu++17</code>) in Linux with POSIX enabled.</p>