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()函数。
    第二是方法的调用,也很简单,可以直接 "对象.原方法名()”就可以了。如:
    [code]
            self.carddll = windll.LoadLibrary("dcrf32.dll")
            self.icdev = self.carddll.dc_init(100,0)
    [/code]
    这里的dc_init()就是原来dll里的方法。
    第三数据类型的转换,这是最复杂的,可以分为4种情况。
    1.简单型(数值、字符、布尔)可以直接传递,不需要变化,比如上面的100,0 及其返回值icdev。
    2.简单类型的指针。也较简单。分别有两种实现方法。
    i.通过byref(参数)
    ii.通过Pointer方法来构造一个指针变量如
    [code]
            tempid = c_ulong(0)
            ptempid = pointer(tempid)
            st2 = self.carddll.dc_card(self.icdev, ModeALL, ptempid)
    [/code]

    [code]
            tempid = c_ulong(0)
            st2 = self.carddll.dc_card(self.icdev, ModeALL, byref(tempid))
    [/code]
    以上两段代码等价
    3.字符串,在dll中往往是char *类型。这里又分为两种情况.
    i.如果传递方向是in很简单,直接把python中的字符串传入就可以了。
    ii.如果是传递方向是out较复杂,需要构造一个字符串buffer,如:
    [code]
    readdata1 = create_string_buffer(16)
    st3 = self.carddll.dc_read(self.icdev, Block8, readdata1)
    readdata = readdata1.value[0:12]
    [/code]
    其中 readdata1就是读出的字符缓冲区,readdata是python字符串
    4.结构体,较复杂需要用ctypes重性定义特殊格式的类。(本次开发没有涉及,就不深入了)
    以下是完整的代码,通过threading.Thread类来实现多线程,通过多线程完成对射频的读取:
    [code]
    from  ctypes import *
    class DevWork(threading.Thread):
        "多线程实现读卡"
        def init(self,window):
            threading.Thread.init(self)
            self.window = window
            self._terminate=False
            #self.__suspend_lock = threading.Lock()
       
        def terminate(self):
            self._terminate = True
     
       
        def OpenDev(self):
            self.carddll = windll.LoadLibrary("dcrf32.dll")
            self.icdev = self.carddll.dc_init(100,0)
            if self.icdev <= 0 :
                return -1
            st = self.carddll.dc_load_key_hex(self.icdev,KEYSET0,Sec2,passwordA)
            if st != 0 :
                self.carddll.dc_exit(self.icdev)
                return -2
            return 1
       
        def run(self):
       
            tempid = c_ulong(0)
            ptempid = pointer(tempid)
            readdata1 = create_string_buffer(16)
            olddata = "a" * 12
            while True:
                time.sleep(3) 
                if self._terminate:
                    break

                st2 = self.carddll.dc_card(self.icdev, ModeALL, ptempid)
                st2 = self.carddll.dc_authentication(self.icdev, KEYSET0, Sec2)
                st3 = self.carddll.dc_read(self.icdev, Block8, readdata1)

                readdata = readdata1.value[0:12]
                if olddata == readdata:  #同一张卡,不再操作
                    continue
                else:
                    self.window.Input(readdata)
                    time.sleep(1)
                olddata = readdata

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

       





  • 在开发过程中不可避免涉及到与系统动态链接库的交互,在python如果需要实现调用系统动态链接库函数,必须使用ctypes模块。ctypes使用相对简单。
    首先是dll的加载,windows下使用windll.LoadLibrary()函数。
    第二是方法的调用,也很简单,可以直接 "对象.原方法名()”就可以了。如:
    [code]
            self.carddll = windll.LoadLibrary("dcrf32.dll")
            self.icdev = self.carddll.dc_init(100,0)
    [/code]
    这里的dc_init()就是原来dll里的方法。
    第三数据类型的转换,这是最复杂的,可以分为4种情况。
    1.简单型(数值、字符、布尔)可以直接传递,不需要变化,比如上面的100,0 及其返回值icdev。
    2.简单类型的指针。也较简单。分别有两种实现方法。
    i.通过byref(参数)
    ii.通过Pointer方法来构造一个指针变量如
    [code]
            tempid = c_ulong(0)
            ptempid = pointer(tempid)
            st2 = self.carddll.dc_card(self.icdev, ModeALL, ptempid)
    [/code]

    [code]
            tempid = c_ulong(0)
            st2 = self.carddll.dc_card(self.icdev, ModeALL, byref(tempid))
    [/code]
    以上两段代码等价
    3.字符串,在dll中往往是char *类型。这里又分为两种情况.
    i.如果传递方向是in很简单,直接把python中的字符串传入就可以了。
    ii.如果是传递方向是out较复杂,需要构造一个字符串buffer,如:
    [code]
    readdata1 = create_string_buffer(16)
    st3 = self.carddll.dc_read(self.icdev, Block8, readdata1)
    readdata = readdata1.value[0:12]
    [/code]
    其中 readdata1就是读出的字符缓冲区,readdata是python字符串
    4.结构体,较复杂需要用ctypes重性定义特殊格式的类。(本次开发没有涉及,就不深入了)
    以下是完整的代码,通过threading.Thread类来实现多线程,通过多线程完成对射频的读取:
    [code]
    from  ctypes import *
    class DevWork(threading.Thread):
        "多线程实现读卡"
        def init(self,window):
            threading.Thread.init(self)
            self.window = window
            self._terminate=False
            #self.__suspend_lock = threading.Lock()
       
        def terminate(self):
            self._terminate = True
     
       
        def OpenDev(self):
            self.carddll = windll.LoadLibrary("dcrf32.dll")
            self.icdev = self.carddll.dc_init(100,0)
            if self.icdev <= 0 :
                return -1
            st = self.carddll.dc_load_key_hex(self.icdev,KEYSET0,Sec2,passwordA)
            if st != 0 :
                self.carddll.dc_exit(self.icdev)
                return -2
            return 1
       
        def run(self):
       
            tempid = c_ulong(0)
            ptempid = pointer(tempid)
            readdata1 = create_string_buffer(16)
            olddata = "a" * 12
            while True:
                time.sleep(3) 
                if self._terminate:
                    break

                st2 = self.carddll.dc_card(self.icdev, ModeALL, ptempid)
                st2 = self.carddll.dc_authentication(self.icdev, KEYSET0, Sec2)
                st3 = self.carddll.dc_read(self.icdev, Block8, readdata1)

                readdata = readdata1.value[0:12]
                if olddata == readdata:  #同一张卡,不再操作
                    continue
                else:
                    self.window.Input(readdata)
                    time.sleep(1)
                olddata = readdata

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

       





  • 赞赞赞......



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


登录后回复
 

与 Odoo 中文社区 的连接断开,我们正在尝试重连,请耐心等待