Was Sie fragen, ist das einzige Problem in Ihrem Beispiel. Nur um zu antworten, was Sie zuerst gefragt haben: Sie müssen den Rückgabetyp der C-Funktion annotieren, so dass Ctypes wissen, dass es eine Speicheradresse ist - ansonsten ist es standardmäßig eine (4 Byte) Ganzzahl (während in jedem 64-Byte-Betriebssystem Zeiger sind) sind 8 Bytes lang).
Dann können Sie Python Seite POINT Strukturen schaffen, indem die (versteckte) „from_address“ Methode in der POINT-Klasse:
test_lib.get_point.restype = c_void_p
p = POINT.from_address(test_lib.get_point())
print(p.x, p.y)
Bevor das funktioniert, aber Sie haben eine grundlegende Frage auf der C Seite: Die POINT-Struktur, die Sie in Ihrem Beispiel deklarieren, existiert nur, während get_point
ausgeführt wird, und wird anschließend freigegeben. Der obige Code würde zu einem Segmentierungsfehler führen.
Ihr C-Code muss Speicher richtig zuordnen. Außerdem sollten Sie Vorkehrungen treffen, um die Zuordnung von Datenstrukturen, die Sie in C zugeordnet haben, zu verhindern. Andernfalls entstehen Speicherlecks, da jeder Aufruf der Funktion in C mehr Speicher zuweist und Sie diesen nicht freigeben. (Beachten Sie, dass dieser Speicher nicht von selbst freigegeben wird, wenn das Python POINT-Objekt den Gültigkeitsbereich verlässt).
Ihr C-Code könnte so aussehen:
#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);
}
Und mit diesem Python Teil:
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
alles sollte einfach funktionieren.
(nur so, dass diese Antwort ein komplettes ctypes Beispiel ist, füge ich die GCC die testlib-Datei erstellen Befehle:
gcc -c -fPIC test.c -o test.o
gcc test.o -shared -o testlib.so
)
Gibt es Gründe, Sie einen Tag für eine 'typedef verwenden 'ed' struct'? Ziemlich nutzlos. Wenn Sie diesen Kommentar nicht verstehen, müssen Sie sich vor dem Start über 'struct's und' typedef' informieren. – Olaf
@Olaf Ich habe immer 'typedef' für' struct's in C für Aliase verwendet. Liegt da etwas falsch daran? –
Ich habe nicht kommentiert mit 'typedef'. Aber dein Kommentar beweist, dass meine Annahme richtig ist. Folgen Sie nicht nur einem Muster, sondern lernen Sie, warum Sie etwas auf eine bestimmte Weise schreiben müssen/sollten! – Olaf