title: What ctypes argument type to use for variably modified multidimensional arrays
body: <p>Using <em>ctypes</em> in python I can freely pass an array to a <em>C</em> function using a pointer to its first element since an array decays to a pointer to its first element in <em>C</em>. So for the <em>C</em> function signature</p>
  <pre><code>void insert_sort(int A[], size_t length);
  </code></pre>
  <p>I can implement the following python wrapper.</p>
  <pre><code>import ctypes
  from typing import List, Callable
  
  def wrap_function(lib: ctypes.CDLL, name: str, restype: object, argtypes: List[object]) -&gt; Callable:
      &quot;&quot;&quot;Simplify wrapping ctypes functions&quot;&quot;&quot;
      func = lib.__getattr__(name)
      func.restype = restype
      func.argtypes = argtypes
      return func
  
  
  lib = ctypes.CDLL(&quot;path/to/library.so&quot;)
  insert_sort = wrap_function(lib, 'insert_sort', None, [ctypes.POINTER(ctypes.c_int), ctypes.c_size_t])
  </code></pre>
  <p>But <em>C</em> also allows one to have arrays of array and whats more variable sized arrays of arrays. For example the <em>C</em> function signature below demonstrates this.</p>
  <pre><code>void matrix_multiply(size_t n, int A[n][n], int B[n][n], int C[n][n]);
  </code></pre>
  <p>How would one wrap this function? To codify my question what goes in the blank below?</p>
  <pre><code>matrix_multiply = wrap_function(lib, 'matrix_multiply', None, [...What goes here...])
  </code></pre>
  <p>If the size of the arrays were known we could simply write</p>
  <pre><code>matrix_multiply = wrap_function(lib, 'matrix_multiply', None, [
      ctypes.c_size_t, ((ctypes.c_int * 4)*4), ((ctypes.c_int * 4)*4), ((ctypes.c_int * 4)*4)
  ])
  </code></pre>
  <p>for arrays of size 4. But what can we do when this number is unknown?</p>