私は現在モジュールに取り込んでおり、を使用して既に受け取ったハンドルでctypes
user32 関数を呼び出そうとしています。今回は、さらに一歩進んで、 で関数を呼び出す代わりに関数プロトタイプを使用したいと思いました。引数を出力パラメータとして宣言するのに問題がありますが。GetWindowText
HWND
FindWindow
ctypes.windll.user32.GetWindowText
lpString
私の最初の試みはこのように見えました:
GetWindowText = cfunc("GetWindowTextA",windll.user32,c_int,
("hWnd",HWND,1),
("lpString",LPCSTR,2),
("nMaxCount",c_int,1)
)
(ここでcfunc
見つけた小さなラッパーです)
このプロトタイプは、呼び出されるとすぐに次の例外を生成します。
chars,name = user32.GetWindowText(handle,255)
TypeError: c_char_p 'out' parameter must be passed as default value
どの出力変数も型でなければならないと考えたPOINTER(...)
ので、定義を次のように変更しました。
GetWindowText = cfunc("GetWindowTextA",windll.user32,c_int,
("hWnd",HWND,1),
("lpString",POINTER(c_char),2),
("nMaxCount",c_int,1)
)
しかし、これも例外をもたらします:
chars,name = user32.GetWindowText(handle,255)
ctypes.ArgumentError: argument 2: <type 'exceptions.TypeError'>: wrong type
GetWindowText
プロトタイピングを使用して関数を正しく呼び出す方法を誰かが知っていることを願っていますctypes
。
編集:
さらなる調査により、少なくとも何らかの形で機能させることができました。私が最初に修正した問題は、cfunc()
which の使用法に間違った呼び出し指定子があったことでした。その関数の正確なコピーを定義して名前をwinfunc()
付けreturn CFUNCTYPE(result, *atypes)((name, dll), tuple(aflags))
、return WINFUNCTYPE(result, *atypes)((name, dll), tuple(aflags))
.
その後、プロトタイピングをさらに検証しました。いくらか渡すと、呼び出し時にオブジェクトが作成("someParameter",POINTER(aType),2)
され、そのオブジェクトへのポインターが関数に渡されます。返されたタプルで、オブジェクトにアクセスできます。これは別の問題を引き起こします。cstring は文字の配列です。そのため、ctypes に を作成するように指示する必要があります。これは、次のようなことを意味します。WINFUNCTYPE
aType
aType
c_char array
GetWindowText = winfunc("GetWindowTextA",windll.user32,c_int,
("hWnd",HWND,1),
("lpString",POINTER(c_char*255),2),
("nMaxCount",c_int,1)
)
うまく動作します。しかし残念なことに、ctypes は で指定されたサイズを無視して常に 255 文字の長さの cstring へのポインターを渡すようになりましたnMaxCount
。
私の意見では、出力パラメーターとして定義された動的にサイズ設定された cstring でその関数を機能させる方法はないと思います。唯一の可能性は、出力パラメーター機能を使用せずにLPCSTR
入力パラメーターとして定義することです。次に、呼び出し先は自分でバッファーを作成し、ctypes.create_string_buffer()
それを関数に渡す必要があります (C の場合と同様)。