Как преобразовать список Python в массив C с помощью ctypes? - PullRequest
38 голосов
/ 10 ноября 2010

Если у меня есть следующие 2 набора кода, как их склеить?

void
c_function(void *ptr) {
    int i;

    for (i = 0; i < 10; i++) {
        printf("%p", ptr[i]);
    }

    return;
}


def python_routine(y):
    x = []
    for e in y:
        x.append(e)

Как я могу вызвать функцию c_ с непрерывным списком элементов в x?Я пытался привести x к c_void_p, но это не сработало.

Я также пытался использовать что-то вроде

x = c_void_p * 10 
for e in y:
    x[i] = e

, но это вызывает синтаксическую ошибку.

Код C явно хочет адрес массива.Как заставить это произойти?

Ответы [ 4 ]

71 голосов
/ 10 ноября 2010

Следующий код работает с произвольными списками:

import ctypes
pyarr = [1, 2, 3, 4]
arr = (ctypes.c_int * len(pyarr))(*pyarr)
8 голосов
/ 10 ноября 2010

С учебник по типам :

>>> IntArray5 = c_int * 5
>>> ia = IntArray5(5, 1, 7, 33, 99)
7 голосов
/ 30 июня 2018

Это объяснение принятого ответа.

ctypes.c_int * len(pyarr) создает массив (последовательность) типа c_int длины 4 ( python3 , python 2 ).Поскольку c_int является объектом, конструктор которого принимает один аргумент, (ctypes.c_int * len(pyarr)(*pyarr) выполняет инициализацию по одному выстрелу для каждого экземпляра c_int из pyarr.Форма , удобнее для чтения :

pyarr = [1, 2, 3, 4]
seq = ctypes.c_int * len(pyarr)
arr = seq(*pyarr)

Используйте функцию type, чтобы увидеть разницу между seq и arr.

1 голос
/ 04 января 2019
import ctypes
import typing

def foo(aqs : typing.List[int]) -> ctypes.Array:
    array_type = ctypes.c_int64 * len(aqs)
    ans = array_type(*aqs)
    return ans

for el in foo([1,2,3]):
    print(el)

это даст:

1
2
3
...