我有一个Windows
python3.7
函数,该函数使用kernel32.dll
成功调用了GetSystemPowerStatus
ctypes
函数,以询问电源状态以查看笔记本电脑是否开启交流电或电池电源。这是一个纯python解决方案。
我想将此功能移植到cygwin
python3.7
。现成的python3
的{{1}}的{{1}}似乎不允许调用Windows dll。我希望使用纯python解决方案,但如有必要,我可以使用C / C ++。有人有这样做的例子吗?
编辑后添加代码(第63-67行)和错误消息:
cygwin
python2.7给出了相同的错误,但在第366行。
已解决。请在下面查看我自己的答案。
答案 0 :(得分:0)
正如您所知,我无法获得kernel32.dll
(尽管它可以与user32
,msvcrt
,kernelbase
等其他DLL一起使用)
我发现了一种非常人为的方法...它使用kernelbase.dll(导出GetModuleHandle
)来获取kernel32.dll
的句柄,然后使用该句柄调用CDLL
可选关键字:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
import ctypes
def main():
# the idea is to load kernelbase.dll which will allow us to call GetModuleHandleW() on kernel32.dll
try:
kernel_base = ctypes.CDLL("/cygdrive/c/windows/system32/kernelbase.dll")
except OSError:
print("Can't load kernelbase.dll...")
return -1
gmhw = kernel_base.GetModuleHandleW
gmhw.argtypes = (ctypes.c_wchar_p, )
gmhw.restype = ctypes.c_void_p
# call GetModuleHandleW on kernel32.dll (which is loaded by default in the Python process)
kernel32_base_addr = gmhw("kernel32.dll")
print(f"Got kernel32 base address: {kernel32_base_addr:#x}")
# now call CDLL with optional arguments
kernel32 = ctypes.CDLL("/cygdrive/c/windows/system32/kernel32.dll", handle=kernel32_base_addr, use_last_error=True)
# test with GetSystemPowerStatus
print(f"GetSystemPowerStatus: {kernel32.GetSystemPowerStatus}")
return 0
if __name__ == "__main__":
sys.exit(main())
答案 1 :(得分:-1)
在发现我可以轻松加载user32.dll
之后,我对源和pdb
和ldd
进行了更多研究。接下来是我的解决方案。
elif _os.name == 'posix' and _sys.platform == 'cygwin':
RTLD_LOCAL = 0 # from /usr/include/dlfcn.h
RTLD_LAZY = 1
RTLD_NOW = 2
RTLD_GLOBAL = 4
RTLD_NODELETE = 8
RTLD_NOLOAD = 16
RTLD_DEEPBIND = 32
kernel32_name = '/proc/cygdrive/c/Windows/System32/kernel32.dll'
kernel32 = CDLL(kernel32_name, mode=RTLD_LAZY | RTLD_NOLOAD)
_GetSystemPowerStatus = kernel32.GetSystemPowerStatus
调用该函数的常见代码是:
_GetSystemPowerStatus.restype = c_bool
_GetSystemPowerStatus.argtypes = [c_void_p,]
_systemPowerStatus = _SystemPowerStatus() # not shown, see ctypes module doc
result = _GetSystemPowerStatus(byref(_systemPowerStatus))
return result, SystemPowerStatus(_systemPowerStatus)
这在
上的Python 2.7、3.6和3.6上可以正常工作$ uname -a
CYGWIN_NT-10.0 host 3.0.1(0.338/5/3) 2019-02-20 10:19 x86_64 Cygwin
感谢大家的帮助。