2012-06-05 1 views
1

와 함께 저는 현재 ctypes 모듈에 점점 그리고 난 이미 FindWindow를 사용하여받은 HWND 핸들로 USER32 기능 GetWindowText를 호출하는 것을 시도하고있다. 이번에는 더 많은 단계를 처리하고 ctypes.windll.user32.GetWindowText 함수를 호출하는 대신 함수 프로토 타입을 사용하려고합니다. 비록 내가 출력 매개 변수로 lpString의 논쟁을 선언하는 데 문제가있어. 내 첫 번째 시도는이 방법으로 보았다 파이썬하는 ctypes : 프로토 타입 LPCSTR [OUT] 매개 변수

:

GetWindowText = cfunc("GetWindowTextA",windll.user32,c_int, 
        ("hWnd",HWND,1), 
        ("lpString",LPCSTR,2), 
        ("nMaxCount",c_int,1) 
       ) 

이 프로토 타입은 즉시 호출 될 때 다음과 같은 예외를 산출한다 (cfunc 내가 here을 발견 조금 래퍼) :

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 

나는 누군가가 제대로 ctypes 프로토 타입을 사용하여 GetWindowText 함수를 호출하는 방법을 알고 있기를 바랍니다.

편집 : 나는 그것이 적어도 어떻게 든 일을 얻을 수있는 추가 연구를 통해

. 내가 고친 첫 번째 문제는 잘못된 호출 지정자가있는 cfunc()의 사용법이었습니다. 그 함수의 정확한 복사본을 정의하고 winfunc()으로 명명하고 return CFUNCTYPE(result, *atypes)((name, dll), tuple(aflags))return WINFUNCTYPE(result, *atypes)((name, dll), tuple(aflags))으로 대체했습니다.

그런 다음 프로토 타입을 추가로 검사했습니다. ("someParameter",POINTER(aType),2)WINFUNCTYPE에 다소 전달하면 호출시 aType 개체가 생성되고 해당 개체에 대한 포인터가 함수에 전달됩니다. 반환 된 튜플에서 aType 개체에 액세스 할 수 있습니다. 이것은 또 다른 문제를 야기한다. cstring은 문자 배열입니다. 그래서 ctypes에 c_char array을 생성하라고 지시해야합니다. 즉, 다음과 같은 의미입니다.

GetWindowText = winfunc("GetWindowTextA",windll.user32,c_int, 
        ("hWnd",HWND,1), 
        ("lpString",POINTER(c_char*255),2), 
        ("nMaxCount",c_int,1) 
       ) 

잘 작동합니다. 그러나 불행하게도, ctypes는 항상 nMaxCount으로 지정된 크기를 무시하고 255 문자 길이의 cstring에 대한 포인터를 전달합니다.

제 의견으로는 출력 매개 변수로 정의 된 동적 크기가있는 cstring을 사용하여 작업 할 수있는 방법이 없다고 생각합니다. 유일한 가능성은 단순히 출력 매개 변수 기능을 사용하지 않고 입력 매개 변수로 LPCSTR을 정의하는 것입니다. 피 호출자는 ctypes.create_string_buffer()을 사용하여 버퍼를 만들어 함수에 전달해야합니다 (C 에서처럼).

답변

2

당신은 밖으로 매개 변수에 대한 문자열 버퍼를 만들어야합니다. 당신은 약간 투명하게하는 기능을 래핑 할 수 있습니다

# python3 
from ctypes import * 

_GetWindowText = WinDLL('user32').GetWindowTextW 
_GetWindowText.argtypes = [c_void_p,c_wchar_p,c_int] 
_GetWindowText.restype = c_int 

def GetWindowText(h): 
    b = create_unicode_buffer(255) 
    _GetWindowText(h,b,255) 
    return b.value 

FindWindow = WinDLL('user32').FindWindowW 
FindWindow.argtypes = [c_wchar_p,c_wchar_p] 
FindWindow.restype = c_void_p 

h = FindWindow(None,'Untitled - Notepad') 
print(GetWindowText(h)) 

또는

이 경우에는 그냥 사용할 수 있습니다 pywin32 :

import win32gui 
h = win32gui.FindWindow(None,'Untitled - Notepad') 
print(win32gui.GetWindowText(h)) 
+0

예 이미 pywin32를 보았습니다.하지만 win32 이외의 곳에서 ctypes를 사용해야하고 persistent 코드를 원하기 때문에 사용하고 싶지 않습니다. (아마도 핸들 등을 교환해야 할 필요가 있습니다). 한편 프로토 타입 패턴 (하나는 일반적인 반환 값이 아니라 일반 반환 값이 아니라 일반 함수로 액세스 할 수 있음)과 Im은 래퍼 솔루션을 접근하거나 단순히 completly로 이동하는 것을 고려 중입니다. "출력 매개 변수"기능을 사용하지 않아도됩니다. – Paranaix

+0

"영구 코드"가 무슨 뜻인지 모르겠지만, pywin32'PyHANDLE' 객체는 핸들을 교환해야 할 경우 원시 윈도우 핸들에서 탈착 할 수 있습니다. http://docs.activestate.com/activepython/2.4/pywin32/PyHANDLE.html 문서를 참조하십시오. 또한 파이썬'c_char_p' 타입은 입력 문자열만을 전달하는 것을 의미합니다. 예를 들어'create_string_buffer (255)'만을 사용하여 출력에 사용할 수있는 버퍼를 만드십시오. –

1

예. 모든 호출에 대해 버퍼를 만들어야합니다. 함수 정의를 수행하게하면 나중에 버퍼에 어떻게 액세스 할 수 있습니까?

는 또한 POINTER(c_char)와 포인터 c_char을 기대하도록 지시해야 할 것, 그리고 단순히 c_char_p 또는 LPSTR.왜 그것이 일어나는 지 잘 모르겠다.

어쨌든,이 작업을해야합니다 :

from ctypes import * 
from ctypes.wintypes import * 

# defs 

FindWindowF = WINFUNCTYPE(HWND, LPSTR, LPSTR) 
FindWindow = FindWindowF(windll.user32.FindWindowA) 

GetWindowTextF = WINFUNCTYPE(c_int, HWND, POINTER(c_char), c_int) 
GetWindowText = GetWindowTextF(windll.user32.GetWindowTextA) 

# code 

text = create_string_buffer(255) 

hwnd = FindWindow(None, 'Untitled - Notepad') 
GetWindowText(hwnd, text, sizeof(text)) 

print text.value 
+0

이것은 내가 내 편집에 쓴 작업 OFC 수행하고 내가 현재 생각 이 질문에 직면하는 문제는 가변 크기의 cstring과 함께 "출력 매개 변수"기능을 사용하는 것입니다. 힙의 Rect 구조체에 출력 Rect * 매개 변수가있는'GetWindowRect()'함수에 대해서는'prototype = WINFUNCTYPE (BOOL, HWND, POINTER (RECT))'으로 프로토 타입을 정의한 다음'paramflags = , "hwnd"), (2, "lprect")'. 마지막으로 func'GetWindowRect = prototype (("GetWindowRect", windll.user32), paramflags)''rect = GetWindowRect (handle)'을 호출 할 수 있습니다. – Paranaix

+0

포인터 문제는 다음에 대한 우려가 있습니다. c_char_p는 실제로 알고있는 한 _ctyped.pyd에 정의 된 네이티브 형식입니다. 이것은 c_char_p! = POINTER (c_char)를 의미합니다. 출력 매개 변수 기능을 사용하려는 경우 paramlist arguement는 항상 POINTER (x) 유형으로 전환합니다. 이렇게하면 호출시 x 객체를 만들고 POINTER (x)를 함수에 전달합니다. 마침내 x 객체를 다시 얻습니다. 이 기능을 사용하지 않더라도 물론 c_char_p 또는이 경우 LPCSTR을 사용할 수 있습니다. – Paranaix