Python & amp; Ctypes: Passer une structure à une fonction en tant que pointeur pour récupérer des données
J'ai regardé à travers d'autres réponses, mais ils ne peuvent pas sembler obtenir que cela fonctionne. J'essaie d'appeler une fonction dans une DLL pour communiquer avec SMBus appareils. Cette fonction reçoit un pointeur vers une struct, qui a un tableau comme l'un de ses champs. alors...
Dans C:
typedef struct _SMB_REQUEST
{
unsigned char Address;
unsigned char Command;
unsigned char BlockLength;
unsigned char Data[SMB_MAX_DATA_SIZE];
} SMB_REQUEST;
Je pense que j'ai pour définir les valeurs de l'Adresse, de Commande et de BlockLength alors que la DLL remplit le tableau de Données.
La fonction qui a besoin de cette structure prend comme un pointeur
SMBUS_API int SmBusReadByte( SMBUS_HANDLE handle, SMB_REQUEST *request );
Donc j'ai mis en place la structure en Python comme suit:
class SMB_REQUEST(ctypes.Structure):
_fields_ = [("Address", c_char),
("Command", c_char),
("BlockLength", c_char),
("Data", type(create_string_buffer(SMB_MAX_DATA_SIZE))]
*Note: j'ai aussi essayé de ctypes.c_char*SMB_MAX_DATA_SIZE pour le type de données*
Pour passer un pointeur vers une structure de ce type à la fonction, j'ai essayé de réagir, d'abord comme suit:
data = create_string_buffer(SMB_MAX_DATA_SIZE)
smb_request = SMB_REQUEST('\x53', \x00', 1, data)
Cela répond:
TypeError: expected string or Unicode object, c_char_Array_32 found
Si j'essaie de quitter le tableau de données, comme suit:
smb_request = SMB_REQUEST('\x53', \x00', 1)
Non, erreur.
Cependant, lorsque j'essaie de la transmettre à la fonction:
int_response = smbus_read_byte(smbus_handle, smb_request))
J'obtiens:
ArgumentError: argument 2: <type 'exceptions.TypeError'>: expected LP_SMB_REQUES
T instance instead of SMB_REQUEST
J'ai essayé de le transmettre comme un pointeur:
int_response = smbus_read_byte(smbus_handle, ctypes.POINTER(smb_request))
et j'obtiens:
----> 1
2
3
4
5
TypeError: must be a ctypes type
Voici comment j'ai configuré l'art types:
smbus_read_byte.argtypes = (ctypes.c_void_p, ctypes.POINTER(SMB_REQUEST))
J'ai essayé de casting mais toujours pas aller. Quelqu'un peut-il éclairer sur ce pour moi?
Mise à jour:
Si j'ai d'abord initialiser la structure comme suit:
smb_request = SMB_REQUEST('\xA6', '\x00', chr(1), 'a test string')
et puis la basse par la référence:
int_response = smbus_receive_byte(smbus_handle, ctypes.byref(smb_request))
Je n'obtiens pas d'erreur. Cependant, la fonction retourne -1 si elle doit retourner '0' pour la réussite et non nulle pour un échec. De vérifier la valeur de smb_request.Données de retour d'une chaîne de test' donc pas de changement.
Toutes les suggestions sur ce qui pourrait se passer ici serait grandement apprécié.
Grâce
Mise à JOUR:
Depuis que j'ai reçu quelques demandes de renseignements au sujet de savoir si ma poignée est correct, voici comment je l'utilise. L'en-tête de fichier de la DLL déclare ce qui suit:
typedef void *SMBUS_HANDLE;
//
// This function call initializes the SMBus, opens the driver and
// allocates the resources associated with the SMBus.
// All SMBus API calls are valid
// after making this call except to re-open the SMBus.
//
SMBUS_API SMBUS_HANDLE OpenSmbus(void);
Donc voici comment j'ai fais ça en python:
smbus_handle = c_void_p() # NOTE: I have also tried it without this line but same result
open_smbus = CDLL('smbus.dll').OpenSmbus
smbus_handle = open_smbus()
print 'SMBUS_API SMBUS_HANDLE OpenSmbus(void): ' + str(smbus_handle)
J'appelle cela avant de faire l'appel à smbus_read_byte(). J'ai essayé de mettre open_smbus.restype = c_void_p()
mais j'obtiens une erreur: TypeError: restype must be a type, a callable, or None
source d'informationauteur Jack | 2010-12-04
Vous devez vous connecter pour publier un commentaire.
Voici un exemple de travail. On dirait que vous êtes de passage le mauvais type de la fonction.
Test Code de la DLL ("cl /W4 /LD x.c" sur Windows)
Code Python
De sortie
Vous y êtes presque. Vous devez utiliser
c_char * SMB_MAX_DATA_SIZE
que le type de la définition deData
. Cela fonctionne pour moi sur Mac OS X:Bibliothèque partagée:
Pilote Python:
Mise à JOUR
Vous rencontrez des problèmes parce que vous devez définir le type de résultat de
open_smbus
àvoid*
. Par défaut, ctypes suppose que les fonctions de retourint
s. Vous devez vous dire ceci:Vous avez été d'avoir une erreur parce que vous avez été en utilisant
c_void_p()
(note de l'extra parenthèses). Il y a une importante distinction entrec_void_p
etc_void_p()
. Le premier est un typeet le dernier est un instance d'un type.c_void_p
représente le type Cvoid*
alors quec_void_p()
représente un pointeur d'instance (avec une valeur par défaut 0).Essayez de changer
à