我试图使用ctypes
模块来调用Windows的Common Item Dialog API。下面显示的代码大致基于MSDN documentation中概述的步骤。它唯一的依赖项是comtypes.GUID
模块。在
import ctypes
from ctypes import byref, POINTER, c_int, c_long
from ctypes.wintypes import HWND, HRESULT
from comtypes import GUID
CLSID_FileOpenDialog = '{DC1C5A9C-E88A-4DDE-A5A1-60F82A20AEF7}'
IID_IFileDialog = '{42F85136-DB7E-439C-85F1-E4075D135FC8}'
#IID_IFileOpenDialog = '{D57C7288-D4AD-4768-BE02-9D969532D960}'
CLSCTX_SERVER = 5
COINIT_APARTMENTTHREADED = 2
FOS_PICKFOLDERS = 32
FOS_FORCEFILESYSTEM = 64
ole32 = ctypes.windll.ole32
CoCreateInstance = ole32.CoCreateInstance
CoInitializeEx = ole32.CoInitializeEx
CoInitializeEx(None, COINIT_APARTMENTTHREADED)
ptr = c_int()
error = CoCreateInstance(
byref(GUID(CLSID_FileOpenDialog)), None, CLSCTX_SERVER,
byref(GUID(IID_IFileDialog)), byref(ptr))
assert error == 0
ptr = ptr.value
c_long_p = ctypes.POINTER(ctypes.c_int)
print('Pointer to COM object: %s' % ptr)
vtable = ctypes.cast(ptr, c_long_p).contents.value
print('Pointer to vtable: %s' % vtable)
func_proto = ctypes.WINFUNCTYPE(HRESULT, HWND)
# Calculating function pointer offset: 3rd entry in vtable; 32-bit => 4 bytes
show_p = ctypes.cast(vtable + 3*4, c_long_p).contents.value
print('Pointer to show(): %s' % show_p)
show = func_proto(show_p)
show(0)
在第一次调用show(0)
之前,一切正常:
(输出可能会有所不同。)为了比较,我在AutoHotkey中执行了相同的步骤,它可以直接访问COM。在
CLSID := "{DC1C5A9C-E88A-4DDE-A5A1-60F82A20AEF7}"
IID := "{42F85136-DB7E-439C-85F1-E4075D135FC8}"
ptr := ComObjCreate(CLSID, IID)
vtable := NumGet(ptr + 0, 0, "Ptr")
show := NumGet(vtbl + 0, 3 * A_PtrSize, "Ptr")
MsgBox ptr: %ptr% vtable: %vtable% show: %A_PtrSize%
DllCall(show, "Ptr", ptr, "Ptr", 44)
生成的宏将按预期弹出“打开文件”对话框。vtable指针偏移量在这两种情况下是相同的,但是只有Python版本会引发访问冲突。在
有人能解释一下吗?在
[我很抱歉没有在适当的地方添加更多的超链接,但是作为一个新用户,我一次只能添加两个超链接。]
背景: 我正在组装一个轻量级模块,它提供了一个本机保存/打开文件对话框,以便在Python脚本中使用。到目前为止,我还没有找到纯Python的实现。那些现有的依赖于UI工具包,比如Tkinter或wxPython。在
解决方案如下:
COM方法接受一个附加参数:“this”指针。它是隐式的,当你从C++调用方法时,C(和cType)必须自己提供。在
换行
进入
^{pr2}$这条线呢
^{3}$进入
你的代码会起作用的。在
相关问题 更多 >
编程相关推荐