Creating cdata of type `REAL (* vertices)[DIM]` in CFFI
<p>I'm trying to build a python interface around some existing <a href="http://www.cs.ox.ac.uk/stephen.cameron/distances/" rel="nofollow">C code</a> with CFFI. As usual with C code trimmed for performance, it is fraught with extensive macros and typedefs.</p>

<p>ATM I am working on replicating following struct</p>

<pre><code>#define DIM     3
typedef double  REAL;
struct Object_structure {
  int numpoints;
  REAL (* vertices)[DIM];
  int * rings;
};
typedef struct Object_structure * Object;
</code></pre>

<p>The function I'm trying to call expects an argument of type <code>Object</code>.</p>

<pre><code>REAL gjk_distance(
   Object obj1, REAL (* tr1)[DIM+1],
   Object obj2, REAL (* tr2)[DIM+1],
   REAL wpt1[DIM], REAL wpt2[DIM],
   struct simplex_point * simplex, int use_seed
   );
</code></pre>

<p>I have written the following python class for representing such an object/struct, but I'm having trouble converting it into the expected cdata object. (For now I just considering a UnitCube, but ultimately I'll want to generalize that.)</p>

<pre><code>class Box:
    def __init__(self, pos):
        self._weakkeydict = weakref.WeakKeyDictionary()
        self.numpoints = 8
        self.rings = [
            8, 12, 16, 20, 24, 28, 32, 36,
            3, 1, 4, -1,
            0, 2, 5, -1,
            1, 3, 6, -1,
            2, 0, 7, -1,
            7, 5, 0, -1,
            4, 6, 1, -1,
            5, 7, 2, -1,
            6, 4, 3, -1]
        x, y, z = pos
        self.vertices = [
            [x+0, y+0, z+0],
            [x+1, y+0, z+0],
            [x+1, y+1, z+0],
            [x+0, y+1, z+0],
            [x+0, y+0, z+1],
            [x+1, y+0, z+1],
            [x+1, y+1, z+1],
            [x+0, y+1, z+1],
        ]

    @property
    def cdata(self):
        self._weakkeydict.clear()

        #ptr_numpoints = ffi.new("int", self.numpoints)
        ptr_rings = ffi.new("int[]", self.rings)
        vertices = [ffi.new("REAL[3]", v) for v in self.vertices]
        ptr_vertices = ffi.new("REAL *[3]", vertices )

        ptr_obj = ffi.new("Object", { 
            'numpoints': self.numpoints,
            'rings': ptr_rings,
            'vertices': ptr_vertices})
        self._weakkeydict[ptr_obj] = (ptr_rings, ptr_vertices, vertices)
        return ptr_obj
</code></pre>

<p>With the above I'm getting <code>IndexError: too many initializers for 'double *[3]' (got 8)</code> in line <code>ptr_vertices = ffi.new("REAL *[3]", vertices )</code> when calling:</p>

<pre><code>box1 = Box((0,0,0)) 
box2 = Box((10,0,0))
d = lib.gjk_distance( 
        [box1.cdata], ffi.NULL,
        [box2.cdata], ffi.NULL,
        ffi.NULL, ffi.NULL, 
        ffi.NULL,  0    )
</code></pre>

<p>To me it seems as if the dimensions got switched somehow. As it should be an 8 element array with 3 element items. 
I'm hoping someone can point me in the right direction here.</p>

<p>If you are creating a single item, use <code>ffi.new('REAL(*)[3]', [1, 2, 3])</code>. The parenthesis around the <code>*</code> is important.</p>

<p>In C, the type <code>REAL(*)[3]</code> means a pointer to array (size=3) of REAL, while <code>REAL*[3]</code> means an array (size=3) of pointer to real. See <a href="http://stackoverflow.com/questions/859634/c-pointer-to-array-array-of-pointers-disambiguation">C pointer to array/array of pointers disambiguation</a> for detail.</p>

<p>Now, you are creating an array of items, CFFI <a href="http://cffi.readthedocs.io/en/latest/ref.html#ffi-new" rel="nofollow">expects an array type</a> instead, <a href="http://stackoverflow.com/a/39938016/224671">as you have already discovered</a>. This can be compared as:</p>

<pre><code>ffi.new('int*', 1)    # ok
ffi.new('int[]', 1)   # wrong
ffi.new('int*', [1, 2, 3])    # wrong
ffi.new('int[]', [1, 2, 3])   # ok

ffi.new('REAL(*)[3]', [0.1, 0.2, 0.3])    # ok
ffi.new('REAL[][3]', [0.1, 0.2, 0.3])     # wrong
ffi.new('REAL(*)[3]', [[0.1, 0.2, 0.3], [0.4, 0.5, 0.6]])    # wrong
ffi.new('REAL[][3]', [[0.1, 0.2, 0.3], [0.4, 0.5, 0.6]])     # ok
</code></pre>

python c cffi