2016-08-25 1 views
-5

Je fais comme suit, mais j'obtiens une erreur.Python passer struct et pointeur sur la fonction c pour l'entrée et la sortie

Y a-t-il des erreurs dans l'utilisation des ctypes, ou quelque chose ne va pas dans les types de paramètres que je passe?

Je pense qu'il peut y avoir trois points doit être pensé:

  1. générons bons paramètres passés à la fonction c en python.

  2. Passez le pointeur avec le type de fonction struct to c.

  3. La structure d'instanciation à droite dépend du tableau donné, si besoin struct dans le code python.

Je suis nouveau pour c, en particulier pointeur.

code c: struct, ansfer.h

typedef unsigned char boolean_T; 


struct emxArray_real_T 
{ 


    double *data; 
    int *size; 
    int allocatedSize; 
    int numDimensions; 
    boolean_T canFreeData; 
}; 

la fonction appelée par python, ansfer.c

void ansferA(const emxArray_real_T *dataArray, double H, emxArray_real_T *TE, 
       emxArray_real_T *Lag) 
{ 

... 

P2 += dataArray->data[a + dataArray->size[0] * b]; 

... 

TE->data[a + TE->size[0] * b] = te; 

Lag->data[a + Lag->size[0] * b] = h; 

... 
} 

puis, gcc -o libansfer.so -shared -fPIC *.c

libansfer.so est généré.

Je réécris le test.py selon les conseils. Ajouter des structures comme suit.

code python: test.py

import numpy as np 
import ctypes 

c_double_p = ctypes.POINTER(ctypes.c_double) 
c_int_p = ctypes.POINTER(ctypes.c_int) 

class emxArray_real_T(ctypes.Structure): 
    _fields_ = [ 
     ("data",   c_double_p), 
     ("size",   c_int_p), 
     ("allocatedSize", ctypes.c_int), 
     ("numDimensions", ctypes.c_int), 
     ("canFreeData", ctypes.c_bool) 
    ] 

indata = np.array([[1.1,1.1,1.1,1.1,1.1,1.1,1.1,1.1,1.1,1.1,1.1,1.1,1.1,1.1,1.1,1.1],[2.2,2.2,2.2,2.2,2.2,2.2,2.2,2.2,2.2,2.2,2.2,2.2,2.2,2.2,2.2,2.2],[3.3,3.3,3.3,3.3,3.3,3.3,3.3,3.3,3.3,3.3,3.3,3.3,3.3,2.2,2.2,2.2]]) 

LL, CC = indata.shape 

TE = np.zeros((LL,LL), dtype=np.double) 
Lag = np.zeros((LL,LL), dtype=np.double) 

SS = np.array([LL, CC]) 
instruct = emxArray_real_T() 
instruct.data = c_double_p(ctypes.c_double(indata.ctypes.data)) 
instruct.size = c_int_p(ctypes.c_int(SS.ctypes.data)) 
instruct.allocatedSize = ctypes.c_int(LL*CC) 
instruct.numDimensions = ctypes.c_int(2) 
instruct.canFreeData = ctypes.c_bool(0) 

ss = np.array([LL, LL]) 
outstruct1 = emxArray_real_T() 
outstruct1.data = c_double_p(ctypes.c_double(TE.ctypes.data)) 
outstruct1.size = c_int_p(ctypes.c_int(ss.ctypes.data)) 
outstruct1.allocatedSize = ctypes.c_int(LL*LL) 
outstruct1.numDimensions = ctypes.c_int(2) 
outstruct1.canFreeData = ctypes.c_bool(0) 

outstruct2 = emxArray_real_T() 
outstruct2.data = c_double_p(ctypes.c_double(Lag.ctypes.data)) 
outstruct2.size = c_int_p(ctypes.c_int(ss.ctypes.data)) 
outstruct2.allocatedSize = ctypes.c_int(LL*LL) 
outstruct2.numDimensions = ctypes.c_int(2) 
outstruct2.canFreeData = ctypes.c_bool(0) 

lib = ctypes.cdll.LoadLibrary('./libansfer.so') 

lib.ansferA(instruct,ctypes.c_double(3), outstruct1, outstruct2) 

mais erreur semblable

Traceback (most recent call last): 
    File "C:\Python27\testfile\test.py", line 106, in <module> 
    lib.ansferA(instruct,ctypes.c_double(3), outstruct1, outstruct2) 
WindowsError: exception: access violation writing 0x0000000000000000 
+3

Le code affiché est à la fois illisible et incomplet. S'il vous plaît prenez le temps de vérifier la lecture, formatez votre question correctement et fournissez un [mcve]. – kaylum

+1

Le C semble requérir des pointeurs vers 'struct emxArray_real_T' comme les deux arguments les plus à droite, mais vous passez des pointeurs en double. Vous devez décrire la structure en ctypes. Il plante probablement quand il a essayé d'accéder à l'un des membres qui sont des pointeurs. – cdarke

+0

'byref (ctypes.c_double (indata.ctypes.data)) 'prend' data' ("un pointeur vers la zone de mémoire du tableau sous la forme d'un entier Python"), puis le convertit en un "double" (_not_ un double pointeur!) puis prend un pointeur vers ce double. 'indata.ctypes.data_as (ctypes.POINTER (ctypes.c_double))' fonctionnerait plutôt à la place, mais regardez ce que cdarke a écrit à propos des structures. – DavidW

Répondre

0

Ce n'est pas une réponse, mais les règles de formatage ne me permettent pas de placer cela comme un commentaire (et encore être lisible).

Le struct ressemble à quelque chose comme ceci:

c_double_p = ctypes.POINTER(ctypes.c_double) 
c_int_p = ctypes.POINTER(ctypes.c_int) 

class emxArray_real_T(ctypes.Structure): 
    _fields_ = [ 
     ("data",   c_double_p), 
     ("size",   c_int_p), 
     ("allocatedSize", ctypes.c_int), 
     ("numDimensions", ctypes.c_int), 
     ("canFreeData", ctypes.c_bool) 
    ] 

I doit deviner le type de canFreeData, boolean_T n'est pas un type standard C.

Puis le struct initialiser avec quelque chose comme:

emxArray_struct = emxArray_real_T(insert values here as parameters) 

Je n'ai pas travaillé avec numpy, donc je ne sais pas si/comment ses types sont mis en correspondance avec ctypes ou types de variables python régulière.

+0

Merci beaucoup. – glen