设为首页 收藏本站
查看: 1066|回复: 0

[经验分享] Python ctypes 里使用 create_string_buffer, addressof, string_at

[复制链接]

尚未签到

发表于 2015-10-26 13:26:50 | 显示全部楼层 |阅读模式
已经写了一篇 blog 里面介绍了如何传入结构体指针的方法,而前不久发现了另外一种传入一整块 buffer 的方案,不用定义 Structure class,直接类似 malloc 那样的方法去执行,就是 create_string_buffer addressof string_at 系列函数,感觉更接近底层调用.
首先修正上篇文档里面的一个问题,就是 load 这个方法已经取消了(当时我使用的好像是 0.9.9.3 版的 ctypes),LoadLibrary 这个接口随着ctypes 1.0 的发布并被集成进 python 2.5,应该是正式确定了名称。
其次注意的是根据源代码里面对函数不同的声明,还得选择采用 cdll 还是 windll 来实例化一个动态库,用 WINAPI 声明的函数需要用 windll.LoadLibrary(dll_file_path)。因为不同的声明导致参数传递的方法不一样,我自己就是费了好长时间的尝试,才搞清楚为什么总是报错"rocedure called with not enough arguments (xx bytes missing) or wrong calling convention"。ctypes 的手册里面还提到另外有oledll, pydll 两种类型.
如果一个 dll 里面即有普通方法定义的函数,也有 WINAPI 定义的函数,而你只希望只 Load 一次动态库,那么就需要 WINFUNCTYPE 或者 CFUNCTYPE 这样的方法来指定不同的函数类型了。
大家都应该机器上安装 XviD 解码器了吧,:)
现在我们分别用两个不同的方法取出 XviD 编码器的缺省配置(C 源代码参考 xvidcore-x.y.z\vfw\src\driverproc.c)

from ctypes import *
DriverProc = windll.LoadLibrary("c:\\windows\\system32\\xvidvfw.dll").DriverProcconfigsize = DriverProc(c_int(0), c_int(0), c_int(0x5000), c_voidp(0), c_voidp(0))  
# 获取结构体大小 configsize
did = DriverProc(c_int(0), c_int(0), c_int(0x0003), c_voidp(0), c_voidp(0))
# 获取访问句柄 did
config = create_string_buffer(configsize, configsize)
# 创建 buffer, 返回一个 Python 对象
pconfig = addressof(config)
# buffer 的地址,让我想起了 C 里面的 &
DriverProc(c_int(did), c_int(0), c_int(0x5000), pconfig, c_voidp(0))
# 这次调用就是把缺省配置复制到传入的内存区域内
s = string_at(pconfig, configsize)
# 最后我们从 pconfig 地址里的内容生成一个字符串对象出来
上面的代码通过 cdll + WINFUNCTYPE 来写就是
from ctypes import *
from ctypes.wintypes import *
xvidvfw = cdll.LoadLibrary("c:\\windows\\system32\\xvidvfw.dll")
# 看好了,这里可用的是 cdllprototype = WINFUNCTYPE(LONG, DWORD, DWORD, UINT, LPARAM, LPARAM)
# LONG 是返回值,DWORD, DWORD, UINT, LPARAM, LPARAM 是参数列表
paramflags = (1, "driverid", 0), \
             (1, "hdriver", 0), \
             (1, "umsg", 0), \
             (1, "para1", 0), \
             (1, "para2", 0)
# 设定一下参数表,以及缺省参数,就可以用 key=value 的方式来传递了
x = prototype(("DriverProc", xvidvfw), paramflags)
# ...
configsize = x(umsg=0x5000)
# 这里只传入一个参数,其它的就自动用缺省的了;而且无需 c_int 这样来转换
did = x(umsg=0x0003)
# .... 以下就不需要注释了吧
config = create_string_buffer(configsize, configsize)
pconfig = addressof(config)
y = x(driverid=did, umsg=0x5000, para1=pconfig)
s = string_at(pconfig, configsize)
最后要说的是通过 dumpbin.exe /exports dll_file_path,就可以查看一个 dll 里面有哪些函数是被 export 出来,可以给我们来调用的(我自己猜测) . dumpbin.exe 可以从 masm32 里面免费获得
update: 在上述第一个例子里面,传入的参数用 addressof 去做一次转换并不是必须的. 可能 ctypes 会在内部自动处理


转自:http://www.dup2.org/node/248

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-131008-1-1.html 上篇帖子: Python 入门教程 4 ---- Date and Time 下篇帖子: selenium + python 自动化测试 学习连载 (一) 环境搭建
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表