2012-11-15 12 views
5

私はPythonからDLLを呼び出そうとしています。 DLLはまっすぐなC言語で書かれており、それについては何もひどく複雑ではありません。これはctypesが正確に作られたものです。しかし、私はDLLの関数呼び出しから返された構造体内で正しい値を得ることに問題があります。渡された構造体の最初の値は正しく返されますが、他の値は返されません。Python ctypesが参照渡しの値を正しく返さない

このコードは、メモリ内のバッファから複数のメッセージを読み取ります。 ReadFirst()/ ReadNext()コーディングパラダイムを使用します。状態を追跡するために渡される "現在のメッセージ"構造体があります。ここ

が現在ReadFirst()/ READNEXT()状態を保持しているC言語の構造体である...ここ

typedef struct 
    { 
    unsigned int   uMsgNum; 
    uint32_t    ulCurrOffset; 
    uint32_t    ulDataLen; 
    Su1553F1_ChanSpec  * psuChanSpec; 
    Su1553F1_Header  * psu1553Hdr; 
    SuCmdWordU   * psuCmdWord1; 
    SuCmdWordU   * psuCmdWord2; 
    uint16_t    * puStatWord1; 
    uint16_t    * puStatWord2; 
    uint16_t    uWordCnt; 
    uint16_t    * pauData; 
    } Su1553F1_CurrMsg; 

はctypesのに書き込まれたctypesの構造体対応物である...

class CurrMsg_1553F1(ctypes.Structure): 
    ''' Data structure for the current 1553 message info structure ''' 
    _pack_ = 1 
    _fields_ = [("MsgNum",  ctypes.c_uint32), 
       ("CurrOffset", ctypes.c_uint32), 
       ("DataLen",  ctypes.c_uint32), 
       ("pChanSpec", ctypes.POINTER(ChanSpec_1553F1)), 
       ("p1553Hdr", ctypes.c_void_p), 
       ("pCmdWord1", ctypes.POINTER(CmdWord)), 
       ("pCmdWord2", ctypes.POINTER(CmdWord)), 
       ("pStatWord1", ctypes.c_void_p), 
       ("pStatWord2", ctypes.c_void_p), 
       ("WordCnt",  ctypes.c_uint16), 
       ("pData",  ctypes.c_void_p)] 

以下で詳細を説明しますが、ReadFirst()/ ReadNext()の呼び出しはMsgNumの値を正しく返しますが、他の値はガベージです。ここではサンプル出力は...

MsgNum 0 CurrOffset 40912728 DataLen 40912732 Messages = 3664897 
MsgNum 1 CurrOffset 40912728 DataLen 40912748 Messages = 60417 
MsgNum 2 CurrOffset 40912728 DataLen 40912748 Messages = 60417 
etc. 

MSGNUMが正しいとReadFirst()/ READNEXT()は、正しい回数を反復しています。ただし、CurrOffset、DataLenの値はガベージです。 (メッセージ値は他のメモリへのポインタから逆参照されていますが、私はまだそうは思いませんが、他のものを修正するまでその値を保存する必要があります。また、おそらく間違っている。)

EnI106Status enI106_Decode_First1553F1 
    (SuI106Ch10Header * psuHeader, 
    void    * pvBuff, 
    Su1553F1_CurrMsg * psuMsg); 

EnI106Status enI106_Decode_Next1553F1 
    (Su1553F1_CurrMsg * psuMsg); 

これらのDLL関数

は()によるデバッグprint文と一緒に呼び出されます

ここ

機能のためのインタフェースである... ...

def __init__(self, PacketIO): 
    self.CurrMsg = CurrMsg_1553F1() 

def Decode_First1553F1(self): 
    Status = self.PacketIO._IrigDataDll.enI106_Decode_First1553F1(ctypes.byref(self.PacketIO.Header), ctypes.byref(self.PacketIO.Buffer), ctypes.byref(self.CurrMsg)) 
    print "MsgNum %d CurrOffset %d DataLen %d Messages = %d" % \ 
     (Decode1553.CurrMsg.MsgNum, Decode1553.CurrMsg.CurrOffset, Decode1553.CurrMsg.DataLen, Decode1553.CurrMsg.pChanSpec.contents.MsgCnt) 
    return Status 

def Decode_Next1553F1(self): 
    Status = self.PacketIO._IrigDataDll.enI106_Decode_Next1553F1(ctypes.byref(self.CurrMsg)) 
    print "MsgNum %d CurrOffset %d DataLen %d Messages = %d" % \ 
     (Decode1553.CurrMsg.MsgNum, Decode1553.CurrMsg.CurrOffset, Decode1553.CurrMsg.DataLen, Decode1553.CurrMsg.pChanSpec.contents.MsgCnt) 
    return Status 

Visual Studio 2005の下でC DLLがコンパイルされます。私はこのDLLをたくさん使用しましたさまざまなCおよびC++ .NETプログラムに問題はありません。

私はctypesと構造体を使用して他のコードの値を返しましたが、うまくいきました。構造体の最初の値はOKですが、後続の値は途切れているため、データの整列の問題のように感じられます。私はパック = 1をctypes構造体に設定し、コンパイルされたDLLコードにバイトアライメントを設定しました。私は各構造体のsizeof printoutを行い、それらが予想されるサイズであることを確認しました。

私はしばらくの間この壁に頭を打ち、アイデアがありません。次は何をしようと思っていますか?

+0

をコーディングすることができるはずです、あなたは(self.CurrMsg)のByRef渡していますが、Decode1553.CurrMsgからフィールドを印刷します。代わりにself.CurrMsgからフィールドを印刷するべきではありませんか? –

答えて

2

C構造体の最初の要素はunsigned intですが、Python構造体はc_uint32です。彼らはあなたのアーキテクチャで同じサイズであると確信していますか?

まず、私はPythonの宣言から_pack_を削除し、Cソースから任意の#pragma packまたは他のアライメント操作になります。それは任意の助けがない場合には

は、私は、問題の原因を追跡するために、次の手順を実行します。既知の場所、ネイティブアラインメントから開始します。

次に...

構造体を反復処理し、各メンバーのオフセットをoffsetof(struct, field)で印刷するCプログラムを作成します。また、このプログラムはFirst()とNext()への呼び出しを行い、バイナリ形式で構造体をファイルに書き出す必要があります。

次に、structモジュールを使用してpythonスクリプトを作成し、Cプログラムから書いた構造体を繰り返し、フィールドサイズとアラインメントの知識を持ってstruct.unpack(...)を呼び出します構造体を適切に定義する書式文字列。

その知識を使用すると、適切にPythonのコードでは、あなたのctypes.Structure

関連する問題