2016-08-25 8 views
-5

次のようにしますが、エラーが発生します。pythonのpass構造体と入出力関数のポインタへのポインタ

ctypesの使用に間違いがありますか、渡すパラメータのタイプに問題がありますか?

  1. はPythonでC関数に渡された右のパラメータを生成します。

    は、私は約考えるべき三点があるかもしれないと思います。

  2. struct to structの型のポインタを渡します。

  3. structが必要な場合は、指定された配列に依存します(pythonコードで構造体が必要です)。

私はc、特にポインタの新機能です。

Cコード:構造体、ansfer.h

typedef unsigned char boolean_T; 


struct emxArray_real_T 
{ 


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

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; 

... 
} 

次いで、gcc -o libansfer.so -shared -fPIC *.c

libansfer.soが生成されます。

私は、アドバイスに従ってtest.pyを書き換えます。次のように構造体を追加します。

の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) 

が、同様のエラー

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

表示されているコードは、判読不能かつ不完全です。あなたの質問を正しく書いて、[mcve]を提供するために、時間をかけて読んでください。 – kaylum

+1

Cは 'struct emxArray_real_T'のポインタを右端の2つの引数として要求していますが、ポインタをdoubleに渡しています。構造体をctypesに記述する必要があります。ポインタであるメンバの1つにアクセスしようとするとクラッシュする可能性があります。 – cdarke

+0

'byref(ctypes.c_double(indata.ctypes。データ)) ''データ '("配列のメモリ領域へのポインタをPythonの整数として ")をとり、それを' double'(_not_aダブルポインタ!)にキャストし、そのダブルへのポインタをとります。 'indata.ctypes.data_as(ctypes.POINTER(ctypes.c_double))'は代わりに代わりに働きますが、cdarkeがstructについて書いたものを見てください。 – DavidW

答えて

0

(これが答えではありませんが、書式設定ルールは、私はコメントとしてこれを配置することはできません。まだ読めるように)。

構造体には次のようになります:

私は canFreeDataの種類と推測してい
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) 
    ] 

boolean_Tは、標準のCタイプではありません。

その後のようなもので、構造体を初期化:

emxArray_struct = emxArray_real_T(insert values here as parameters) 

私はnumpyのに働いていないので、その種類はctypesの、あるいは通常のPythonの変数の型にマッピングされているか/どうかは知りません。

+0

ありがとうございます。 – glen

関連する問題