То, что вы спрашиваете, является единственной проблемой в вашем примере. Чтобы ответить только на то, что вы спросили вначале: вы должны аннотировать тип возврата функции C, так что ctypes знает, что это адрес памяти - в противном случае по умолчанию это (4 байта) целое число (в то время как в любой 64-байтной ОС указатели 8 байтов).
Затем вы можете создать Python стороны POINT структуру, используя (скрытый) метода «FROM_ADDRESS» в классе POINT:
test_lib.get_point.restype = c_void_p
p = POINT.from_address(test_lib.get_point())
print(p.x, p.y)
До этого работает, однако, у вас есть более фундаментальный вопрос о С сторона: Структура POINT, которую вы объявляете на вашем примере, существует только в то время, когда get_point
работает и освобождается после этого. Приведенный выше код приведет к ошибке сегментации.
Ваш код C должен правильно распределять память. Кроме того, вы должны принять меры для освобождения структур данных, которые вы выделяете в C, - иначе у вас будет утечка памяти, поскольку каждый вызов функции в C выделяет больше памяти, и вы не освобождаете это. (Обратите внимание, что эта память не будет освобождена сама по себе, когда объект POINT Python выходит за рамки).
Ваш код C может выглядеть так:
#include <stdlib.h>
#include <stdio.h>
typedef struct point {
int x;
int y;
} POINT;
POINT *get_point()
{
POINT *p;
POINT initial = {1, 2};
p = malloc(sizeof(POINT));
*p = initial;
return p;
}
void free_point(POINT *p)
{
free(p);
}
И с этой Python части:
from ctypes import *
import os
lib_name = '/testlib.so'
test_lib = CDLL(os.getcwd() + lib_name)
class POINT(Structure):
_fields_ = [('x', c_int),
('y', c_int)]
test_lib.get_point.restype = c_void_p
p1 = POINT.from_address(test_lib.get_point())
print (p1.x, p1.y)
test_lib.free_point(byref(p1))
del p1
все должно работать.
(а именно так, что этот ответ полный пример ctypes, я добавить GCC команды для создания файла testlib:
gcc -c -fPIC test.c -o test.o
gcc test.o -shared -o testlib.so
)
Любая причина вы используете тег для 'ЬурейеЕ 'ed' struct'? Довольно бесполезно. Если вы не понимаете этот комментарий, вам нужно узнать о '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' ''' '' '' '' '' '' '' '' '' '' '' '' '. – Olaf
@Olaf Я всегда использовал 'typedef' для' struct 'в C для псевдонимов. Есть что-то по своей сути неправильно? –
Я не комментировал использование 'typedef'. Но ваш комментарий подтверждает мое предположение правильным. Не просто следуйте шаблону, но узнайте **, почему ** вы должны/должны написать что-то конкретным образом! – Olaf