4

As seen here How do I convert a Python list into a C array by using ctypes? this code will take a python array and transform it to a C array.

import ctypes
arr = (ctypes.c_int * len(pyarr))(*pyarr)

Which would the way of doing the same with a list of lists or a lists of lists of lists?

For example, for the following variable

list3d = [[[40.0, 1.2, 6.0, 0.3], [50.0, 4.2, 0, 0]], [[40.0, 1.2, 6.0, 0.3], [50.0, 4.2, 0, 0]], [[40.0, 1.2, 6.0, 0.3], [50.0, 4.2, 0, 0]]]

I have tried the following with no luck:

([[ctypes.c_double * 4] *2]*3)(*list3d)
# *** TypeError: 'list' object is not callable

(ctypes.c_double * 4 *2 *3)(*list3d)
# *** TypeError: expected c_double_Array_4_Array_2 instance, got list

Thank you!

EDIT: Just to clarify, I am trying to get one object that contains the whole multidimensional array, not a list of objects. This object's reference will be an input to a C DLL that expects a 3D array.

1
  • this is not a good solution. for a list a=[[1,2,3,4],[2,3,5,6]] , you can do arr = [ (ctypes.c_int * len(key))(*key) for key in a ] Commented Oct 17, 2013 at 18:59

3 Answers 3

2

It works with tuples if you don't mind doing a bit of conversion first:

from ctypes import *

list3d = [
    [[0.0, 1.0, 2.0, 3.0], [4.0, 5.0, 6.0, 7.0]], 
    [[0.2, 1.2, 2.2, 3.2], [4.2, 5.2, 6.2, 7.2]],
    [[0.4, 1.4, 2.4, 3.4], [4.4, 5.4, 6.4, 7.4]],
]

arr = (c_double * 4 * 2 * 3)(*(tuple(tuple(j) for j in i) for i in list3d))

Check that it's initialized correctly in row-major order:

>>> (c_double * 24).from_buffer(arr)[:]
[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 
 0.2, 1.2, 2.2, 3.2, 4.2, 5.2, 6.2, 7.2, 
 0.4, 1.4, 2.4, 3.4, 4.4, 5.4, 6.4, 7.4]

Or you can create an empty array and initialize it using a loop. enumerate over the rows and columns of the list and assign the data to a slice:

arr = (c_double * 4 * 2 * 3)()

for i, row in enumerate(list3d):
    for j, col in enumerate(row):
        arr[i][j][:] = col
Sign up to request clarification or add additional context in comments.

Comments

0

I made the change accordingly

a = [[[40.0, 1.2, 6.0, 0.3], [50.0, 4.2, 0, 0]], [[40.0, 1.2, 6.0, 0.3], [50.0, 4.2, 0, 0]], [[40.0, 1.2, 6.0, 0.3], [50.0, 4.2, 0, 0]]]
arr = (((ctypes.c_float * len(a[0][0])) * len(a[0])) * len(a))
arr_instance=arr()
for i in range(0,len(a)):
  for j in range(0,len(a[0])):
    for k in range(0,len(a[0][0])):
      arr_instance[i][j][k]=a[i][j][k]

The arr_instance is what you want.

2 Comments

Unfortunately I am looking for only one object. I have added extra information. Thanks anyway!
That´s it! However eryksun's answer is more concise. Thx
0

I wanted a solution to use for arbitrarily-dimensioned lists of lists. Here is a recursive method.

import ctypes

def list_into_ctype(l, ctype):
    currentlevel = []
    for i in l:
        if type(i) is list:
            currentlevel.append(list_into_ctype(i, ctype))
        else:
            currentlevel.append(ctype(i))
    
    result = (type(currentlevel[0]) * len(l))(*currentlevel)
    
    return(result)

running on the example:

list3d = [
    [[0.0, 1.0, 2.0, 3.0], [4.0, 5.0, 6.0, 7.0]], 
    [[0.2, 1.2, 2.2, 3.2], [4.2, 5.2, 6.2, 7.2]],
    [[0.4, 1.4, 2.4, 3.4], [4.4, 5.4, 6.4, 7.4]],
]

out = list_into_ctype(list3d, ctypes.c_double)

>>> out
<__main__.c_double_Array_4_Array_2_Array_3 object at 0x0000024C95AB0340>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.