在开发过程中不可避免涉及到与系统动态链接库的交互,在python如果需要实现调用系统动态链接库函数,必须使用ctypes模块。ctypes使用相对简单。
首先是dll的加载,windows下使用windll.LoadLibrary()函数。
第二是方法的调用,也很简单,可以直接 "对象.原方法名()”就可以了。如:
<br />        self.carddll = windll.LoadLibrary("dcrf32.dll")<br />        self.icdev = self.carddll.dc_init(100,0)<br />
这里的dc_init()就是原来dll里的方法。
第三数据类型的转换,这是最复杂的,可以分为4种情况。
1.简单型(数值、字符、布尔)可以直接传递,不需要变化,比如上面的100,0 及其返回值icdev。
2.简单类型的指针。也较简单。分别有两种实现方法。
i.通过byref(参数)
ii.通过Pointer方法来构造一个指针变量如
<br />        tempid = c_ulong(0)<br />        ptempid = pointer(tempid)<br />        st2 = self.carddll.dc_card(self.icdev, ModeALL, ptempid)<br />
<br />        tempid = c_ulong(0)<br />        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  ctypes import *<br />class DevWork(threading.Thread):<br />    "多线程实现读卡"<br />    def __init__(self,window):<br />        threading.Thread.__init__(self)<br />        self.window = window<br />        self._terminate=False<br />        #self.__suspend_lock = threading.Lock()<br />    <br />    def terminate(self):<br />        self._terminate = True<br />  <br />    <br />    def OpenDev(self):<br />        self.carddll = windll.LoadLibrary("dcrf32.dll")<br />        self.icdev = self.carddll.dc_init(100,0)<br />        if self.icdev <= 0 :<br />            return -1<br />        st = self.carddll.dc_load_key_hex(self.icdev,KEYSET0,Sec2,passwordA)<br />        if st != 0 :<br />            self.carddll.dc_exit(self.icdev)<br />            return -2<br />        return 1<br />    <br />    def run(self):<br />     <br />        tempid = c_ulong(0)<br />        ptempid = pointer(tempid)<br />        readdata1 = create_string_buffer(16)<br />        olddata = "a" * 12<br />        while True:<br />            time.sleep(3)   <br />            if self._terminate:<br />                break<br /><br />            st2 = self.carddll.dc_card(self.icdev, ModeALL, ptempid)<br />            st2 = self.carddll.dc_authentication(self.icdev, KEYSET0, Sec2)<br />            st3 = self.carddll.dc_read(self.icdev, Block8, readdata1)<br /><br />            readdata = readdata1.value[0:12]<br />            if olddata == readdata:   #同一张卡,不再操作<br />                continue<br />            else:<br />                self.window.Input(readdata)<br />                time.sleep(1)<br />            olddata = readdata<br /><br />
其中terminate()用来实现结束线程
OpenDev()用来打开设备
run()里边有个大循环,用来实现连续读取卡片内容。