Python中如何将C++调用dll的方式转换成Python实现?
主要是想通过 Python 使用 WCaptureX.dll 里面的函数,涉及到的 dll 可以到这个软件的安装目录获取
https://wordweb.info/free/
这里提供了 C++调用 dll 的方法
https://sites.google.com/a/deskperience.com/wordcapturexdoc/deployment/using-native-dlls—no-com
另外的一些相关文档
函数文档 https://sites.google.com/a/deskperience.com/wordcapturexdoc/wcapturex/wcapturex-interface/capture-method
例子 https://sites.google.com/a/deskperience.com/wordcapturexdoc/wcapturex/wcapturex-interface/capture-method/visual-c
是否有高手愿意帮忙把这个方法转成 Python 的,指导下我如何使用?为了表示诚意,我愿意出至少 50 元,大家先别嫌少,如果确实能搞定,我愿意再加点,谢谢各位!
我折腾出这种来,貌似也还是不知道怎么用
from ctypes import *
# help(cdll.WCaptureX.CreateCOMObject)
print(cdll.WCaptureX.CreateCOMObject)
Python中如何将C++调用dll的方式转换成Python实现?
50 太多了,从没做过这么大的项目。。怎么办。
import ctypes
import os
# 1. 加载DLL
# 方式1:指定完整路径
dll_path = r"C:\path\to\your\library.dll"
my_dll = ctypes.WinDLL(dll_path) # Windows系统
# 或 my_dll = ctypes.CDLL(dll_path) # 非Windows系统
# 方式2:如果DLL在系统路径中
# my_dll = ctypes.cdll.LoadLibrary("library.dll")
# 2. 定义函数原型
# 假设C++函数:int add(int a, int b)
my_dll.add.argtypes = [ctypes.c_int, ctypes.c_int] # 参数类型
my_dll.add.restype = ctypes.c_int # 返回值类型
# 3. 调用函数
result = my_dll.add(5, 3)
print(f"5 + 3 = {result}")
# 4. 处理复杂数据类型示例
# 假设C++函数:void process_array(float* arr, int length)
my_dll.process_array.argtypes = [ctypes.POINTER(ctypes.c_float), ctypes.c_int]
my_dll.process_array.restype = None
# 创建数组并调用
arr = (ctypes.c_float * 5)(1.0, 2.0, 3.0, 4.0, 5.0)
my_dll.process_array(arr, 5)
# 5. 结构体示例
class MyStruct(ctypes.Structure):
_fields_ = [
("x", ctypes.c_int),
("y", ctypes.c_float),
("name", ctypes.c_char * 20)
]
# 假设C++函数:MyStruct* create_struct()
my_dll.create_struct.restype = ctypes.POINTER(MyStruct)
struct_ptr = my_dll.create_struct()
print(f"x={struct_ptr.contents.x}, y={struct_ptr.contents.y}")
# 6. 字符串处理
# 假设C++函数:const char* get_message()
my_dll.get_message.restype = ctypes.c_char_p
message = my_dll.get_message()
print(f"Message: {message.decode('utf-8')}")
# 7. 回调函数示例
# 定义回调类型
CALLBACK = ctypes.CFUNCTYPE(None, ctypes.c_int)
# 假设C++函数:void set_callback(CALLBACK cb)
my_dll.set_callback.argtypes = [CALLBACK]
def my_callback(value):
print(f"Callback received: {value}")
# 保持回调函数引用避免被垃圾回收
cb_instance = CALLBACK(my_callback)
my_dll.set_callback(cb_instance)
关键点说明:
- 加载DLL:使用
ctypes.WinDLL(Windows)或ctypes.CDLL(其他系统) - 函数原型:必须通过
argtypes和restype明确定义参数和返回类型 - 数据类型映射:
c_int→intc_float→floatc_char_p→char*POINTER(type)→ 指针类型
- 数组传递:使用
(ctype * length)语法创建数组 - 结构体:继承
ctypes.Structure并定义_fields_ - 字符串:注意编码解码,
c_char_p对应C字符串 - 回调函数:使用
CFUNCTYPE定义回调类型,保持引用避免GC
常见问题处理:
- 调用约定:如果DLL使用
__stdcall,用ctypes.WinDLL;__cdecl用ctypes.CDLL - 64位系统:确保Python和DLL都是32位或都是64位
- 内存管理:C++分配的内存通常需要C++释放
一句话建议: 用ctypes直接映射C++函数原型,注意数据类型转换和内存管理。
我看成了 50w,抱歉,打扰了
如果是以技术讨论的形式询问不但不会让人反感,而且说请喝星巴克的话不仅成本会降低而且有更多人愿意帮忙。而不是给人这种你的工作量只值 50 块钱的感觉。
自行检索 python win32com
看来技术真的不值钱 所以你自己弄吧
技术看来真的不值钱了 +1
曾经有过 mfc 转成 py 的经历。。不难吧 你搜搜 复制粘贴巴拉巴拉就完了
不好意思,我膨胀了…
我以为就我一个看成 50 万 🤣
哈哈,看评论乐了。不过我正好有个例子不知道楼主用不用得上 https://gist.github.com/beebird/9c37adf19a8436ccdd264a9beb09a8d1
50 太多了,怕干不好当不起啊
对于这种问题不给点 money 让人家白白帮我,我觉得也是不现实,但是学生党又拿不出多少来……
楼主很隐晦的说大家 talk is cheap。。
谢谢!
和你的代码类似的例子之前我也看过几个,但我主要是看不懂那些 C++代码,所以也就无从下手了
https://stackoverflow.com/questions/252417/how-can-i-use-a-dll-file-from-python
善用谷歌和 Stack Overflow,说实话你这个 50 块是在侮辱你自己的信息获取能力··
#14
手头只有爪机,你就只百度 Python win32com 就有例子了
https://www.cnblogs.com/jasonli-01/articles/6612020.html
为了更方便,可以先用 regsvr32 注册一下 DLL
你知道,这个帖子最大的败笔是什么么?
如果只是纯技术请教就别谈钱,会的自然告诉你
如果是外包项目就别扯太多技术,更别提整个 50 块钱的事
你说会的人告诉你了,这 50 要还是不要?
要: 打发要饭呢?
不要: 有偿的操作,当外包干的,还得顶着心里压力,不要就亏了
50 还不够中饭点个外卖
要是标题没悬赏下面回复就是“课后作业自己做”,“知识付费”乱七八糟的了,合着 v2 一群外包接单的
技术无价,你这 50 块钱是在侮辱各位大佬。。。
我觉得搞计算机的
花钱让别人帮忙写自己的 project
是一种侮辱自己的行为
FanWell 正解…
刚想说为啥那么多 wrapper 不用,看了一眼链接发现 COM 的…
微软亲自挖坑咱也没啥可说的…
17 楼那个 stackoverflow 最高票数 ctype 答案有可能不能用,但是楼层里 win32com 那个可能可以用…
貌似问题是没错,错在了提钱,还提个 50 块,哈哈
谢谢两位!
我按文档里的注册了 dll
https://sites.google.com/a/deskperience.com/wordcapturexdoc/wcapturex/register-wcapturex
我的命令
C:\Users\i>regsvr32 “C:\Program Files\WordWeb\WCaptureX.dll"
然后我的代码
from win32com.client import Dispatch
zk = Dispatch(“WCaptureX”)
估计也不对,出现如下异常
Traceback (most recent call last):
File “C:\Users\i\AppData\Local\Programs\Python\Python36-32\lib\site-packages\win32com\client<a target=”_blank” href=“http://dynamic.py” rel=“nofollow noopener”>dynamic.py", line 89, in _GetGoodDispatch
IDispatch = pythoncom.connect(IDispatch)
pywintypes.com_error: (-2147221005, ‘无效的类字符串’, None, None)
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File “D:\BaiduYunDownload\编程\Python<a target=”_blank" href=“http://Win32COM.py” rel=“nofollow noopener”>Win32COM.py", line 3, in <module>
zk = Dispatch(“WCaptureXLib”)
File “C:\Users\i\AppData\Local\Programs\Python\Python36-32\lib\site-packages\win32com\client<a target=”_blank" href=“http://init.py” rel=“nofollow noopener”>init.py", line 95, in Dispatch
dispatch, userName = dynamic._GetGoodDispatchAndUserName(dispatch,userName,clsctx)
File “C:\Users\i\AppData\Local\Programs\Python\Python36-32\lib\site-packages\win32com\client<a target=”_blank" href=“http://dynamic.py” rel=“nofollow noopener”>dynamic.py", line 114, in _GetGoodDispatchAndUserName
return (_GetGoodDispatch(IDispatch, clsctx), userName)
File “C:\Users\i\AppData\Local\Programs\Python\Python36-32\lib\site-packages\win32com\client<a target=”_blank" href=“http://dynamic.py” rel=“nofollow noopener”>dynamic.py", line 91, in _GetGoodDispatch
IDispatch = pythoncom.CoCreateInstance(IDispatch, None, clsctx, pythoncom.IID_IDispatch)
pywintypes.com_error: (-2147221005, ‘无效的类字符串’, None, None)
[Finished in 1.2s]
我可以免费帮你试试。
要自己研究的话,找 C 语言调用 COM 的代码。
个人理解 COM 接口本质是一个记录函数指针的 struct,取到函数指针后 call 就行了。
多谢相助!在下对 win32 编程基本没什么认识,希望在你的指引下让我这小白上道~
#26
名称参数大概写错了,可以借助你可以跑通的语言或者工具查看一下
https://technet.microsoft.com/en-us/library/d0kh9f4c(fr-fr).aspx
你也可以用 win32api 调用 CreateCOMObject,那就是 #27 的方案,第一次写麻烦点,不过对加深理解非常有帮助。
另外能否提供一下示例代码?
不知道你具体要哪方面的代码,我从文档里翻到了这些
https://sites.google.com/a/deskperience.com/wordcapturexdoc/wcapturex/create-wcapturex-object
https://sites.google.com/a/deskperience.com/wordcapturexdoc/deployment/using-native-dlls—no-com
https://sites.google.com/a/deskperience.com/wordcapturexdoc/wcapturex/wcapturex-interface/capture-method/visual-c
要直接运行就能使用的代码。
谢谢!
这里有各种语言的 demo
https://github.com/yanivyhc/WordCaptureSamples
IDispatch 是一个提供了动态特性的 COM 接口,可以实现不固定的函数。一般来说一些较高级的语言会封装这个接口,如 VB C# Delphi,#26 的代码也是使用这个接口。
而 C/C++ 一般不会使用这个接口,因为在没有封装的情况下使用起来较为麻烦。
最终选用了 comtypes https://github.com/enthought/comtypes 这个模块。它同时支持一般的 COM 接口以及 IDispatch,且仅依赖内置的 ctypes 模块。
要么你别提钱。
我误打误撞地似乎找到了可以用的方式,如下
from win32com.client import Dispatch
WCaptureX = Dispatch("{8F267988-0CA4-418C-8F94-B4BC5862B390}")
print(WCaptureX.GetCursorInfo(None) )
在我的电脑上,CLSID 是{8F267988-0CA4-418C-8F94-B4BC5862B390},不知道在别的机器上 CLSID 会不会变?
或者可以趁此学一下 c++?。。
谈钱伤感情,我错了,各位!
看过程,想起了当年被迫在 linux 下调用 dll 的折腾死人的一周
给你打个折,48 元。
"谈钱伤感情,我错了,各位!"
这句话我要反驳一下。
拜托,请问我们有什么感情?不和你谈钱,那谈什么?谈梦想?
钱不多,但有为知识付费的意识,这个难得
#38
不会变,是常量,例如 Excel.* 也有对应的 CLSID,也可以互相转换。官方 SDK 里肯定也有定义的。
还是你理解我!理解万岁!
谢谢大哥不断的指教!
我现在写出的代码如下
from win32com.client import Dispatch
import win32gui
import mouse
import time
from threading import Timer
WCaptureX = Dispatch("{8F267988-0CA4-418C-8F94-B4BC5862B390}")
WInput = Dispatch("{4B484CCE-9120-49B7-A5F2-B8B183BFD808}")
def onMouseClicked():
# x,y=mouse.get_position()
# windowHandle = win32gui.WindowFromPoint((x,y))
# windowClassName= win32gui.GetClassName(windowHandle)
# print(win32gui.GetClassName(windowHandle)) WInput.Hwnd=None
windowHandle,x,y=WCaptureX.GetCursorInfo()
WInput.Hwnd=windowHandle
WInput.StartX=x
WInput.StartY=y
# WInput.EndX=x+100
# WInput.EndY=y+100
WResult=WCaptureX.Capture(WInput)
print(WResult.TEXT ,WResult.Paragraph )
mouse.on_click(onMouseClicked) # 实际是 released event
mouse.wait(button=‘right’, target_types=(‘double’, ))
我试了下 Word 2016 取词也是没问题,但是 Chrome 和 sumatraPDF 之类的软件就无法取词,估计是我没有找到正确的使用方式吧。
据我所知,国内的欧路词典也是用这套工具,该软件在 Chrome 和 sumatraPDF 里取词没问题……
我之前用过内置的 ctypes 调用过 dll,感觉还挺好用的你可以去尝试一下
#47
既然能跑通了那接下来的实现一般就是翻文档的事情了,加油吧
看得我五味杂陈
用 ctypes 我只能走到这一步就不知道下一步怎么走了
from ctypes import *
print(cdll.WCaptureX.CreateCOMObject)
其实吧,我觉得,钱不重要
楼主长个记性吧,以后这种别提钱就好了
CLSID 是不会变的。如果你会的话那我就不写了。
“一般人们总认为要让别人做点事情,就应该给他们奖励,不管多少、 不论大小,有总比没有的好,但其实不然”
“第一种方案纯粹依赖人们的内在动力,第二种则 与经济利益挂钩。那么这两种比较而言,哪种方式起到的效果更好呢? 第一种方案中,无偿献血是一种公益行为,人们愿意在这个时候做点贡 献,会自愿参加献血。而第二种方案因为有物质激励,人们自然而然地 会将献血看成一种经济行为。10 元的补助根本就是杯水车薪,数目实在 太小,起不到激励的作用,没有多少人会愿意为了拿到 10 元去卖血。所 以,没奖要比有小奖更能引导人们做好事,或者做我们希望他们做的事。 当然,如果献血给的钱特别多,比如一万元,那自然有很多人愿意去献 血,但我们比较的不是给一万元和不给钱,比如一万元,那自然有很多人愿意去献 血,但我们比较的不是给一万元和不给钱时人们献血的意愿,而是给 10 元和不给钱时人们献血的意愿。
同样,当我还在耶鲁大学念书的时候,经常需要找一些学生帮我做 问卷。当时我还是一个穷学生,付不起多少钱。我发现如果我请别人帮 我做问卷然后给他们 1 美元的报酬,大多数人都不愿意帮我做。后来,我 索性就不给钱了,直接请他们帮我做问卷,这样反而有比较多的人愿意 帮忙。”
摘录来自: 未知作者. “别做正常的傻瓜”。iBooks.
你的引用道出了我在这篇帖子里的处境,万分感谢!
阁下能否推荐些你觉得大多数人都值得一看的书来看看?
其实是干技术的,都接受不了技术不值钱这个事实。
这个属于你把工作量化成 50 块钱了。。。一般做程序员的都不会觉得自己好几个小时就值 50,下次直接请教下方向就行了,剩下的自己摸索。
这…就值 50?
悬赏 和 50 元 放一起。 让大家开心了一把。
楼主不是坏人。
鉴定完毕。
为什么大家都把帖子标题里面的“至少”给忽略了
好问题
HR 发招聘启示的时候 工资都是范围 为什么大家一般只着重看范围的下限呢?
题主搞定没
没搞定告诉你到哪里抄代码
https://bitbucket.org/pyglet/pyglet/src/11fcff3d96d71619d55354bea6a9adc07efc8afc/pyglet/com.py?at=default
pyglet 项目,纯 Python 做 opengl 外部 0 依赖
涉及到 windows 上的一些肯定的 ctypes 上
50 元的讨论。
搞定了一部分,见 47 楼
做这种事情,包括你说的那个项目,感觉都还是要懂些 C 或 C++才能入手,不然的话步履维艰啊
ctypes 调用 dll 函数就像是普通 python 函数调用一样,但是参数必须用 ctypes 中基本数据类型进行包裹,我记得官方网站上有相关教程还比较详细的
3Q !但是在我现在这个应用场景下用 ctypes 调用 dll 函数似乎难度又上了一个层次,我只能写出这种来就进行不下去了
from ctypes import *
print(cdll.WCaptureX.CreateCOMObject)
难度不高,先通过 ctypes 导入 dll 然后准备好参数,通过 ctypes 调用并得到结果,这个流程并没有什么难度,可能只是你不熟悉库,直接百度 google 搜索一些基本教程很快就能上手。



