Odoo中文社区可以通过以下三个域名访问:shine-it.net , odoocn.org,odoo.net.cn

原论坛用户的基本信息和发帖这里都予以保留,请注意:原论坛用户无需重新注册新用户,但是您的密码需要重置

开发人员可以登录gitter讨论组: http://gitter.im/odoo-china/Talk, 需要github账号

如果您登录系统碰到问题,请在微信公众号留言:

Python开发调用DLL之ctypes初体验



  • 在开发过程中不可避免涉及到与系统动态链接库的交互,在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()里边有个大循环,用来实现连续读取卡片内容。

       





  • 赞赞赞......



  • python可以用来操作单片机吗