2015-10-16 3 views
1

На Python 2.7.10:GetProcAddress странное поведение на Python 3.4

>>> from ctypes import windll 
>>> windll.kernel32.GetProcAddress(windll.kernel32.GetModuleHandleA('kernel32'), 'LoadLibraryW') 

Возвращает не нулевой результат. Но то же самое на Python 3.X всегда возвращает null.

>>> from ctypes import windll 
>>> windll.kernel32.GetProcAddress(windll.kernel32.GetModuleHandleA('kernel32'), 'LoadLibraryA') 
0 
# and other variants 
>>> windll.kernel32.GetProcAddress(windll.kernel32.GetModuleHandleA('kernel32'), 'LoadLibraryW') 
0 
>>> windll.kernel32.GetProcAddress(windll.kernel32.GetModuleHandleW('kernel32'), 'LoadLibraryA') 
0 
>>> windll.kernel32.GetProcAddress(windll.kernel32.GetModuleHandleW('kernel32'), 'LoadLibraryW') 
0 

Что не так и как исправить (если это возможно)?

ответ

1

GetProcAddress является немного необычным с точки зрения обработки строк для имени функции. Поскольку имена экспортируемых функций всегда кодируются с 8-битным текстом, аргумент имени процедуры имеет тип LPCSTR.

Строка типа Python 2.7, str не является Юникодом, а при передаче в ctypes по умолчанию используется кодировка текста как 8 бит. Строковый тип Python 3.x - Unicode, а при передаче в ctypes по умолчанию используется кодировка текста как 16 бит. Отсюда и провал.

Используйте argtypes и restype, чтобы уточнить о типах и решить эту проблему.

 
>>> from ctypes import * # just for this answer, to save typing 
>>> GetModuleHandle = windll.kernel32.GetModuleHandleW 
>>> GetModuleHandle.argtypes = [c_wchar_p] 
>>> GetModuleHandle.restype = c_void_p 
>>> kernel32 = GetModuleHandle('kernel32') 
>>> kernel32 
2004418560 
>>> 2004418560 
2004418560 
>>> GetProcAddress = windll.kernel32.GetProcAddress 
>>> GetProcAddress.argtypes = [c_void_p, c_char_p] 
>>> GetProcAddress.restype = c_void_p 
>>> LoadLibraryW = GetProcAddress(kernel32, b'LoadLibraryW') # force 8 bit encoding 
>>> LoadLibraryW 
2004509856 
+0

Большое спасибо за разъяснения! Это работает: windll.kernel32.GetProcAddress (windll.kernel32.GetModuleHandleW ('kernel32'), b'LoadLibraryW ') – kate

Смежные вопросы