跳转至内容
  • 版块
  • 标签
  • 热门
  • 用户
  • 群组
皮肤
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • 默认(Flatly)
  • 不使用皮肤
折叠

Odoo 中文社区

  1. 主页
  2. 版块
  3. Python 开发
  4. Python开发调用DLL之ctypes初体验

Python开发调用DLL之ctypes初体验

已定时 已固定 已锁定 已移动 Python 开发
4 帖子 3 发布者 13.9k 浏览
  • 从旧到新
  • 从新到旧
  • 最多赞同
登录后回复
此主题已被删除。只有拥有主题管理权限的用户可以查看。
  • M 离线
    M 离线
    mihi
    写于 最后由 编辑
    #1

    在开发过程中不可避免涉及到与系统动态链接库的交互,在python如果需要实现调用系统动态链接库函数,必须使用ctypes模块。ctypes使用相对简单。
    首先是dll的加载,windows下使用windll.LoadLibrary()函数。
    第二是方法的调用,也很简单,可以直接 "对象.原方法名()”就可以了。如:

    <br />&nbsp; &nbsp; &nbsp; &nbsp; self.carddll = windll.LoadLibrary(&quot;dcrf32.dll&quot;)<br />&nbsp; &nbsp; &nbsp; &nbsp; self.icdev = self.carddll.dc_init(100,0)<br />
    


    这里的dc_init()就是原来dll里的方法。
    第三数据类型的转换,这是最复杂的,可以分为4种情况。
    1.简单型(数值、字符、布尔)可以直接传递,不需要变化,比如上面的100,0 及其返回值icdev。
    2.简单类型的指针。也较简单。分别有两种实现方法。
    i.通过byref(参数)
    ii.通过Pointer方法来构造一个指针变量如

    <br />&nbsp; &nbsp; &nbsp; &nbsp; tempid = c_ulong(0)<br />&nbsp; &nbsp; &nbsp; &nbsp; ptempid = pointer(tempid)<br />&nbsp; &nbsp; &nbsp; &nbsp; st2 = self.carddll.dc_card(self.icdev, ModeALL, ptempid)<br />
    



    <br />&nbsp; &nbsp; &nbsp; &nbsp; tempid = c_ulong(0)<br />&nbsp; &nbsp; &nbsp; &nbsp; st2 = self.carddll.dc_card(self.icdev, ModeALL, byref(tempid))<br />
    


    以上两段代码等价
    3.字符串,在dll中往往是char *类型。这里又分为两种情况.
    i.如果传递方向是in很简单,直接把python中的字符串传入就可以了。
    ii.如果是传递方向是out较复杂,需要构造一个字符串buffer,如:

    <br />readdata1 = create_string_buffer(16)<br />st3 = self.carddll.dc_read(self.icdev, Block8, readdata1)<br />readdata = readdata1.value[0:12]<br />
    


    其中 readdata1就是读出的字符缓冲区,readdata是python字符串
    4.结构体,较复杂需要用ctypes重性定义特殊格式的类。(本次开发没有涉及,就不深入了)
    以下是完整的代码,通过threading.Thread类来实现多线程,通过多线程完成对射频的读取:

    <br />from&nbsp; ctypes import *<br />class DevWork(threading.Thread):<br />&nbsp; &nbsp; &quot;多线程实现读卡&quot;<br />&nbsp; &nbsp; def __init__(self,window):<br />&nbsp; &nbsp; &nbsp; &nbsp; threading.Thread.__init__(self)<br />&nbsp; &nbsp; &nbsp; &nbsp; self.window = window<br />&nbsp; &nbsp; &nbsp; &nbsp; self._terminate=False<br />&nbsp; &nbsp; &nbsp; &nbsp; #self.__suspend_lock = threading.Lock()<br />&nbsp; &nbsp; <br />&nbsp; &nbsp; def terminate(self):<br />&nbsp; &nbsp; &nbsp; &nbsp; self._terminate = True<br />&nbsp; <br />&nbsp; &nbsp; <br />&nbsp; &nbsp; def OpenDev(self):<br />&nbsp; &nbsp; &nbsp; &nbsp; self.carddll = windll.LoadLibrary(&quot;dcrf32.dll&quot;)<br />&nbsp; &nbsp; &nbsp; &nbsp; self.icdev = self.carddll.dc_init(100,0)<br />&nbsp; &nbsp; &nbsp; &nbsp; if self.icdev &lt;= 0 :<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return -1<br />&nbsp; &nbsp; &nbsp; &nbsp; st = self.carddll.dc_load_key_hex(self.icdev,KEYSET0,Sec2,passwordA)<br />&nbsp; &nbsp; &nbsp; &nbsp; if st != 0 :<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; self.carddll.dc_exit(self.icdev)<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return -2<br />&nbsp; &nbsp; &nbsp; &nbsp; return 1<br />&nbsp; &nbsp; <br />&nbsp; &nbsp; def run(self):<br />&nbsp; &nbsp;  <br />&nbsp; &nbsp; &nbsp; &nbsp; tempid = c_ulong(0)<br />&nbsp; &nbsp; &nbsp; &nbsp; ptempid = pointer(tempid)<br />&nbsp; &nbsp; &nbsp; &nbsp; readdata1 = create_string_buffer(16)<br />&nbsp; &nbsp; &nbsp; &nbsp; olddata = &quot;a&quot; * 12<br />&nbsp; &nbsp; &nbsp; &nbsp; while True:<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; time.sleep(3)&nbsp;  <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if self._terminate:<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break<br /><br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; st2 = self.carddll.dc_card(self.icdev, ModeALL, ptempid)<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; st2 = self.carddll.dc_authentication(self.icdev, KEYSET0, Sec2)<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; st3 = self.carddll.dc_read(self.icdev, Block8, readdata1)<br /><br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; readdata = readdata1.value[0:12]<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if olddata == readdata:&nbsp;  #同一张卡,不再操作<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; continue<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else:<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; self.window.Input(readdata)<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; time.sleep(1)<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; olddata = readdata<br /><br />
    


    其中terminate()用来实现结束线程
    OpenDev()用来打开设备
    run()里边有个大循环,用来实现连续读取卡片内容。

       



    1 条回复 最后回复
    0
    • mrshellyM 离线
      mrshellyM 离线
      mrshelly
      写于 最后由 编辑
      #2

      赞赞赞......

      1 条回复 最后回复
      0
      • D 离线
        D 离线
        demo
        写于 最后由 编辑
        #3

        python可以用来操作单片机吗

        1 条回复 最后回复
        0

        • 登录

        • 没有帐号? 注册

        • 登录或注册以进行搜索。
        • 第一个帖子
          最后一个帖子
        0
        • 版块
        • 标签
        • 热门
        • 用户
        • 群组