2017-03-24 6 views
0

J'ai essayé de lire toutes les questions/réponses sur ce sujet, mais je n'ai rien trouvé à faire. Tout ce que j'essaie de faire est d'envoyer une structure à un objet partagé, puis de le renvoyer et d'être accessible.Ctypes: mappage d'un pointeur renvoyé à une structure

J'ai réussi à créer une structure OK, et je peux la transmettre à l'objet partagé. Je sais cela car cela fonctionne très bien si vous renvoyez une valeur spécifique de la structure. La définition de la structure en Python peut être vu ci-dessous:

class ROW(ctypes.Structure): 
    _fields_ = [("Address",ctypes.c_int16), 
       ("FirstRegister",ctypes.c_int16), 
       ("NumberOfRegisters",ctypes.c_int16), 
       ("Sampling", ctypes.c_int16)] 

class CONNECTOR(ctypes.Structure): 
    _fields_ = [("NumberOfRows", ctypes.c_int16), 
       ("Rows", ROW * 200)] 

# Initialise an array of connectors (CON1, CON2, CON11, CON12) 
ConArray = CONNECTOR * 4 
con = ConArray() 

# Initialise an array of ROW struct 
RowArray = ROW * 200 
row = RowArray() 

Je peuple alors la structure avec des données à partir d'une base de données SQLite et peut accéder aux données spécifiques à l'aide con[n].Rows[m].Address etc.

Je suis en train d'envoyer juste un moment connecteur à la fois, et renvoyer exactement la même structure.

Le code correspondant peut être vu ci-dessous:

testlib = ctypes.cdll.LoadLibrary('_example.so') 
x = testlib.square_array 
x.argtype = ctypes.POINTER(CONNECTOR) 
x.restype = ctypes.POINTER(CONNECTOR) 

y = x(ctypes.byref(con[0])) 

J'ai essayé plusieurs méthodes d'appel de la fonction, mais celui-ci semble être le plus prometteur. Le problème est lorsque j'essaie et puis accéder à des valeurs spécifiques avec y.Rows[0].Address[0], une erreur se produit: AttributeError: 'LP_CONNECTOR' object has no attribute 'Rows'.

Si au contraire, je viens d'appeler directement la fonction:

x = testlib.square_array(ctypes.byref(con[0])) 

Je reçois un int que je suppose que représente une adresse mémoire, par exemple: 35664848.

J'ai essayé toutes sortes d'options mais je ne suis pas familier avec C (un collègue s'occupera de tout le côté C du code). Y a-t-il des solutions proposées? Je me sens comme si je manquais juste une petite chose, mais il m'a fallu plusieurs jours juste pour atteindre ce point.

Mise à jour: Ajout de code C

Le code C peut être vu ci-dessous:

example.c:

#include "example.h" 

CONNECTOR* square_array(CONNECTOR* con) 
{ 
    printf("Value of Row 0 Address%i\n",con->Rows[0].Address); 
    return (con); 
} 

example.h:

struct ROW; 
struct CONNECTOR; 

typedef struct { 
    short int Address; 
    short int FirstRegister; 
    short int NumberOfRegisters; 
    short int Sampling; 
}ROW; 

typedef struct { 
    short int NumberOfRows; 
    ROW Rows[200]; 
}CONNECTOR; 

CONNECTOR Connectors[4]; 
+0

A quoi ressemble la déclaration de la fonction 'square_array'? – CristiFati

+0

Désolé, j'ai mis à jour ma question pour l'inclure. Il s'appelle 'square_array' car nous avons édité un exemple précédent trouvé. Ce ne sera pas le nom final. L'instruction 'printf()' imprime le résultat correct lors de l'accès à une valeur spécifique. Cependant, je ne sais pas quoi faire avec la structure retournée complète. –

Répondre

1

I déjà créé un petit exemple de mon propre. Après avoir regardé de plus près le code Python, j'ai pu comprendre l'en-tête de la fonction (et j'ai également ajouté un corps factice).

Le problème est simple, la fonction renvoie un pointeur CONNECTOR, afin d'accéder à ses membres, vous devez d'abord le "déréférencer", sinon vous obtiendrez le AttributeError. Voici votre code (modifié un petit peu):

testlib = ctypes.cdll.LoadLibrary("_example.so") 
testfunc = testlib.square_array 
testfunc.argtype = ctypes.POINTER(CONNECTOR) 
testfunc.restype = ctypes.POINTER(CONNECTOR) 

pconnector0 = testfunc(ctypes.byref(con[0])) 
connector0 = pconnector0.contents 
print(connector0.NumberOfRows) 
print(connector0.Rows[0].Address) 

Le « secret » réside dans pconnector0.contents qui effectue le « déréférencement ».

En marge, la ligne de code y.Rows[0].Address[0] déclenche une TypeError en raison de la [0] à la fin: Address est un int et ne peut pas être indexé (ne définit pas __getitem__).

En ce qui concerne la deuxième approche (appeler la fonction directement), c'est le même problème. Voici un code de travail:

pconnector1 = testlib.square_array(ctypes.byref(con[0])) 
connector1 = pconnector1.contents 
print(type(connector1)) 

Remarque: je Python 2.7.10 sur Win10 x64, mais rien ici devrait être Python version ou plate-forme spécifique.

+0

Merci beaucoup. J'ai juste remarqué que j'essayais d'indexer l'adresse mais je n'avais aucune idée de '.contents'. Le problème était que j'essayais de saisir les structures, les pointeurs et les ctypes en même temps, et que je manquais la partie de déréférencement. Le code fonctionne bien maintenant; et maintenant j'ai une base pour intégrer un code utile. –

+0

Vous êtes les bienvenus !!! – CristiFati