C Funktion in Python aufrufen (Parameter ist ein struct)

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
zander180_0
User
Beiträge: 29
Registriert: Samstag 18. Juli 2009, 19:54

Hallo,

Ich möchte eine Funktion einer Hardware API, welche in C geschrieben ist aufrufen. Die ansteuerungssoftware für die Hardware ist in Python. Dir Funktion der API benötigt als Parameter ein Struct als Pointer. Dabei beinhaltet das Struct einen Parameter der ein weiteres struct benötigt.

Wie kann ich diese Funktion mit Python aufrufen und die jeweiligen Parameter mitgeben? Wie kann ich ein struct Aus c inmpython schreiben? Geht das auch ohne ctypes?
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hallo!

Suchst du vielleicht das ctypes-Modul?

Sebastian
Das Leben ist wie ein Tennisball.
zander180_0
User
Beiträge: 29
Registriert: Samstag 18. Juli 2009, 19:54

Nein, wie ich das oben genannte Problem lösen kann. Sprich ein Pointer auf ein struct a un d ein weiters struct b in dem struct a. Wie kann ich das programmieren?
BlackJack

@zander180_0: Naja, das geht mit dem `ctypes`-Modul.
zander180_0
User
Beiträge: 29
Registriert: Samstag 18. Juli 2009, 19:54

Das hab ich mir gedacht aber wie kann ich das umsetzen? Kann mir mal jemand bitte Ei Beispiel zum o.g. Problem geben?
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hallo.
zander180_0 hat geschrieben:Das hab ich mir gedacht aber wie kann ich das umsetzen? Kann mir mal jemand bitte Ei Beispiel zum o.g. Problem geben?
Das hat die Dokumentation zum Modul schon für uns erledigt ;-)
Das Leben ist wie ein Tennisball.
zander180_0
User
Beiträge: 29
Registriert: Samstag 18. Juli 2009, 19:54

Ich hab bereits folgendes probiert aber weiss nicht ob es richtig ist. Die C-Funktion: test(porthandle handle, struct*param);
Das handle habe ich und bin mir auch sicher das das richtig ist. Python:
Class Signal(Structure):
[("a",c_int),("b",c_int)]
Class param(Structure):
[("Signal",Signal)
("test",c_int)]
Point = Signal(1,2)
Parameter=param(Point,5)
Ptr_Parameter = pointer(Parameter)
test(handle,Ptr_Parameter)

Ist das so richtig oder hab ich was falsch gemacht?
Natürlich hab ich ctypes eingebunden und die entsprechende dll für die C-Funktion
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

So sollte das in etwa gehen:

Code: Alles auswählen

class Signal(Structure):
    _fields_ = [
    ('a', c_short),
    ('b', c_short)]

class Param(Structure):
    _fields_ = [
    ('signal', Signal),
    ('test', c_int)]

param = Param()
test(handle, byref(param))
Wirst du vermutlich noch etwas anpassen müssen. `byref()` kann immer dann eingesetzt werden, wenn eine Funktion einen Zeiger erwartet, du ihn aber innerhalb von Python nicht benötigst. Das ist performanter, weil nur eine Art Fake konstruiert wird und sollte daher bevorzugt werden. Es kann übrigens nicht schaden, wenn du uns mal die C-Bibliothek nennst, da man dir dann wahrscheinlich besser helfen kann.

Und bitte antworte nachher nicht mit einem "geht aber nicht", sondern zeige den Codestand und die ggf geworfene Exception. Und wende den Knopf "python" (unterhalb der anderen Formatierungsbuttons) auf den Code an, damit er besser lesbar ist. Dann würdest du auch merken, dass er in seiner jetzigen Form nicht mal durch den Parser geht, was übrigens auch funktioniert, wenn man vor dem Fragen erstmal ausprobiert. :)
zander180_0
User
Beiträge: 29
Registriert: Samstag 18. Juli 2009, 19:54

C-Code:

typedef u8_t G_Signal_ByteOrder_t;

typedef struct {
u8_t Size; // in bits
G_Signal_ByteOrder_t ByteOrder; //= little Endian
u16_t Offset; // in bits
} G_Signal;



typedef u8_t G_CyclicMsgs_Ramp_Direction_t;

#define G_CYCLIC_MSGS__RAMP__DIRECTION__UP \
((G_Can_CyclicMsgs_Ramp_Direction_t) 0x01)


typedef struct {
u32_t Id; //0x123
G_Signal_t Signal;

G_CyclicMsgs_Ramp_Mode_t Mode; //1
G_CyclicMsgs_Ramp_Direction_t Direction; //1
u16_t MinValue; //0

u16_t MaxValue; //15
u16_t UpdateRate; //1

float64_t Increment; //1

u32_t RampSum; //0
u16_t NumberOfFlanks; //0
u8_t reserved1; //0
u8_t reserved2; //0
} G_Can_CyclicMsgs_Ramp_Define_Parameters_t;


und nun meine Umsetzung in Python:
zander180_0
User
Beiträge: 29
Registriert: Samstag 18. Juli 2009, 19:54

Sorry, hatte vergessen den python-code einzufügen. Hier nun alles noch mal komplett.

C-Code:

Code: Alles auswählen

typedef u8_t  G_Signal_ByteOrder_t;

typedef struct {
	u8_t  Size;  // in bits
	G_Signal_ByteOrder_t  ByteOrder; //= little Endian
	u16_t  Offset;  // in bits
} G_Signal;



typedef u8_t  G_CyclicMsgs_Ramp_Direction_t;

#define G_CYCLIC_MSGS__RAMP__DIRECTION__UP  \
	((G_Can_CyclicMsgs_Ramp_Direction_t) 0x01)


typedef struct {
	u32_t  Id;	//0x123
	G_Signal_t  Signal;	

	G_CyclicMsgs_Ramp_Mode_t  Mode;		//1
	G_CyclicMsgs_Ramp_Direction_t  Direction;	//1
	u16_t  MinValue;	//0

	u16_t  MaxValue;	//15
	u16_t  UpdateRate;	//1

	float64_t  Increment;	//1

	u32_t  RampSum;		//0
	u16_t  NumberOfFlanks;	//0
	u8_t  reserved1;	//0
	u8_t  reserved2;	//0
} G_Can_CyclicMsgs_Ramp_Define_Parameters_t;

und nun meine Umsetzung in Python:

Code: Alles auswählen

from ctypes import *

porthandle = c_uint(0) 
point_porthandle = pointer(porthandle)

idMode = c_ubyte(0) 
Id = c_uint(0x123) 

class signal(Structure):
       _fields_=[("Size",c_ubyte), ("Byteorder",c_ubyte),("Offset",c_ushort)]
       
point = signal(4,0,8)

class parameters(Structure):
       _fields_=[("Id",c_uint),
        ("Signal",signal),
        ("Mode",c_ubyte),
        ("Direction",c_ubyte),
        ("MinValue",c_ushort),
        ("MaxValue",c_ushort),
        ("UpdateRate",c_ushort),
        ("Increment",c_uint64),
        ("RampSum",c_uint),
        ("NumberOfFlanks",c_ushort),
        ("reserved1",c_ubyte),
        ("reserved2",c_ubyte)]
       
foo= parameters(Id,(4,0,8),1,1,0,15,1,1,0,0,0,0)
ptr = pointer(foo)

error = GAPI_can.G_CyclicMsgs_Ramp_Define(porthandle,ptr)

Ich habe es bis jetzt noch mit dem Pointer umgesetzt.
Was habe ich falsch gemacht
Zuletzt geändert von Anonymous am Donnerstag 19. August 2010, 20:05, insgesamt 1-mal geändert.
Grund: C-Quelltext in Code-Tags gesetzt.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Man kann Beiträge auch nachträglich Editieren und muss nicht alles noch einmal posten ;-) Und für C-Code könnte man auch Code-Tags verwenden ...
Das Leben ist wie ein Tennisball.
BlackJack

@zander180_0: Ich habe nur mal so kurz drübergeschaut und mir ist `Increment` aufgefallen. Willst Du da wirklich den Wert 4.9406564584124654e-324 für übergeben? Das wäre nämlich eine Ganzahl 1 als 64-Bit Fliesskommazahl interpretiert.

Statt `c_ushort` würde ich auch `c_uint16` verwenden. Das mag vielleicht das gleiche sein, muss es aber nicht.
zander180_0
User
Beiträge: 29
Registriert: Samstag 18. Juli 2009, 19:54

Ich hatte gedacht, dass ich die Datentypen, welche das struct auf der Seite von c exakt übernehmen muss. Deshalb hatte ich c_ushort usw. genommen. Der c-Code ist von einer API einer Hardware. Ich bin somit für die parametrierung nich verantwortlich. Mich interessiert ob ich das alles richtig umgesetzt habe vor allem mit dem struct im struct sowie die Zuweisung der Parameter und das Aufrufen der Funktion.
BlackJack

@zander180_0: Weil der C-Code `u16_t` verwendet nimmst Du `c_ushort` statt `c_uint16` und `c_uint64` statt `c_double`? Das muss ich jetzt nicht verstehen, oder!?
zander180_0
User
Beiträge: 29
Registriert: Samstag 18. Juli 2009, 19:54

Ok, wenn die Sache so ist, dann lass ich mich gern belehren. Welche Parameter sollten wie geaendert werden?
Ich Wäre über jeden Rat dankbar.
Antworten