2017-03-24 15 views
0

このトピックに関するすべての質問/回答を読み込もうとしましたが、何もできませんでした。私がしようとしているのは、共有オブジェクトに構造体を送り、それを返してアクセス可能にすることだけです。Ctypes:返されたポインタを構造体にマッピングする

私は構造体を作成できました。これは共有オブジェクトにうまく伝えることができます。構造体から特定の値を返すとうまくいくので、私はこれを知っています。 Pythonで構造体の定義は、以下に見られることができます。

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

は、私は、SQLiteのデータベースからデータを持つ構造体を移入し、使用して特定のデータにアクセスすることができcon[n].Rows[m].Addressなど

私は現在、1つだけ送信しようとしていますコネクタを一度に使用し、まったく同じ構造体を返します。

関連するコードは、以下に見られることができます。

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

私は関数を呼び出し、多くの異なる方法を試してみましたが、この1つは最も有望であると思われます。問題は、y.Rows[0].Address[0]で特定の値にアクセスしようとすると、エラーが発生します:AttributeError: 'LP_CONNECTOR' object has no attribute 'Rows'

代わりにした場合、私は直接関数を呼び出す:35664848

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

は、私はメモリアドレス、例えばを表し仮定intを受けます。

私はあらゆる種類のオプションを試しましたが、私はCには全く慣れていません(同僚はコードのC側すべてを扱います)。提案されたソリューションはありますか?私はちょうど1つの小さなものが欠けているように感じますが、この点に到達するだけで何日もかかりました。

更新:追加されたCコードは

Cコードは、見ることができる。

は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

'square_array'関数の宣言はどのように見えますか? – CristiFati

+0

申し訳ありませんが、私はそれを含めるために私の質問を更新しました。私たちが見つけた先の例を編集したので、これは 'square_array'と呼ばれます。それは最終的な名前ではありません。 'printf()'ステートメントは、特定の値にアクセスしているときに正しい結果を出力します。しかし、私は返された構造全体をどうすればよいか分かりません。 –

答えて

1

I私自身の小さな例をすでに作成しています。 Pythonコードを詳しく見てから、関数ヘッダーを理解することができました(また、ダミーボディも追加しました)。

問題は簡単で、関数はCONNECTORポインタを返します。そのメンバーにアクセスするには、最初に参照解除する必要があります。そうでなければAttributeErrorが返されます。ここにあなたのコードが(少し修正)です:

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) 

「秘密」は「逆参照」を実行するpconnector0.contentsにあります。側と

コードy.Rows[0].Address[0]の行が末尾にあるため[0]TypeErrorをトリガする注意:Addressintあり、インデックスを付けることができない(__getitem__を定義していません)。

第2のアプローチ(関数を直接呼び出す)に関しては、同じ問題です。私はWin10 x64のにのPython 2.7.10 を使用しますが、ここでは何もPythonのバージョンやプラットフォーム固有べきではない:

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

:ここではいくつかの作業コードです。

+0

ありがとうございました。私はアドレスを索引付けしようとしていたことに気づいたが、 '.contents'については全く知らなかった。問題は、構造とポインタとctypを一度に把握しようとしていて、逆参照部分が見付かりませんでした。コードは今すぐうまくいく。今では便利なコードを統合するための基礎があります。 –

+0

あなたは大歓迎です! – CristiFati

関連する問題