Python から DLL を呼び出そうとしています。DLL はストレート C で書かれており、それほど複雑なことは何もありません。これは、ctypes がまさにそのために作成されたものです。ただし、DLL 関数呼び出しから返された構造体内で正しい値を取得するのに問題があります。渡された構造体の最初の値は正しく返されますが、他の値は返されません。
このコードは、メモリ内のバッファーから複数のメッセージを読み取ります。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 の値はガベージです。(Messages の値は、他のメモリへのポインターから逆参照されます。私はまだその権利を持っているとは思いませんが、この他の問題が修正されるまで、その値を保存する必要があります。CurrOffset と DataLen が間違っている場合、pChanSpec へのポインターはもおそらく間違っています。)
関数のインターフェイスは次のとおりです...
EnI106Status enI106_Decode_First1553F1
(SuI106Ch10Header * psuHeader,
void * pvBuff,
Su1553F1_CurrMsg * psuMsg);
EnI106Status enI106_Decode_Next1553F1
(Su1553F1_CurrMsg * psuMsg);
これらの DLL 関数は、(印刷ステートメントのデバッグと共に) によって呼び出されます...
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
C DLL は Visual Studio 2005 でコンパイルされます。私はこの DLL をさまざまな C および C++ .NET プログラムで問題なく使用しました。
ctypes と structs を使用して他のコードで値を返しましたが、問題なく動作しているようです。構造体の最初の値は問題ありませんが、後続の値はかなりずれているため、これはデータ アライメントの問題のように「感じられます」。ctypes 構造体でpack =1 を設定し、コンパイルされた DLL コードでバイト アラインメントを設定しました。各構造体の sizeof 出力を行い、それらが予想されるサイズであることを確認しました。
私はしばらくの間、この壁に頭をぶつけていて、アイデアがありません。次に何を試すかについて何か考えはありますか?