Ctypes Python: прототип с параметром LPCSTR [out]Python

Программы на Python
Ответить
Anonymous
 Ctypes Python: прототип с параметром LPCSTR [out]

Сообщение Anonymous »

Сейчас я захожу в модуль 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)
)
( — это небольшая оболочка, которую я нашел здесь)

Этот прототип выдает следующее исключение при вызове:

Код: Выделить всё

    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: : wrong type
Надеюсь, кто-нибудь знает, как правильно вызывать функцию GetWindowText, используя прототипирование ctypes.

Изменить:

Благодаря дальнейшим исследованиям я смог заставить ее работать, по крайней мере, как-то. Первой проблемой, которую я исправил, было использование 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. Это означает что-то вроде:

Код: Выделить всё

GetWindowText = winfunc("GetWindowTextA",windll.user32,c_int,
("hWnd",HWND,1),
("lpString",POINTER(c_char*255),2),
("nMaxCount",c_int,1)
)
работает отлично. Но, к сожалению, ctypes теперь будет передавать указатель на cstring, длина которого ВСЕГДА составляет 255 символов, игнорируя размер, указанный nMaxCount.

На мой взгляд, я думаю, что невозможно заставить эту функцию работать с cstring динамического размера, определенной как выходной параметр. Кажется, единственной возможностью является просто отказаться от функции выходного параметра и определить LPCSTR в качестве входного параметра. Затем вызываемому абоненту необходимо создать собственный буфер с помощью ctypes.create_string_buffer() и передать его функции (так же, как в C).

Подробнее здесь: https://stackoverflow.com/questions/108 ... -parameter
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»