• python3调dll库复盘


    对c程序员来说,写python简直就是打开了一片新天地。

    首先要确认下动态库文件是32位的还是64位,python程序要对应。

    先定义一个类loaddll来封装dll库里对应接口函数,一般提供dll库的人都会提供一个.h文件,我们参考这个头文件来封装对应的函数。

    加载dll文件

    import ctypes
    
    class loaddll():
        def __init__(self):
            try:
                self.dll = ctypes.cdll.LoadLibrary('dcltd.dll')
                print('load ok')
            except Exception as e:
                print(e)

    根据头文件中的内容,继续在类loaddll添加函数,函数名字可一样,可不一样。假设头文件中有这样一个函数

    bool DCLTInit(int maxnodes);

    有一个int型数据入参,返回值是布尔型。那这些都要做对应的转换,对应的python代码如下

        def DCLTInit(self, maxnodes):
            try:
                self.dll.DCLTInit.restype = ctypes.c_bool
                self.dll.DCLTInit.argtype = ctypes.c_int
                result = self.dll.DCLTInit(int(maxnodes))
                if result:
                    print('init function ok')
                else:
                    print('error')
            except Exception as e:
                print(e)
    restype表示返回值类型,ctypes.c_bool是c类型的布尔;argtype表示的入参类型,如果是多个入参,比如两个,整形和char*,argtypes = (ctypes.c_int,c_char_p)。如下面这个例子
        def BCAddNode(self, ip, port):
            try:
                self.dll.DCAddNode.restype = ctypes.c_int
                self.dll.DCAddNode.argtypes = (ctypes.c_char_p, ctypes.c_int)
                c_ip = ctypes.c_char_p()
                c_ip.value = ip.encode('gbk')
                no = self.dll.DCAddNode(c_ip, int(port))
                return no
            except Exception as e:
                print(e)

    接下来写个demo测试下:

    hdll = loaddll()
    hdll.DCLTInit(1)
    no = hdll.DCAddNode('10.243.141.16', 5800)
    print(no)

    运行结果:

    load ok
    init function ok
    0
    
    Process finished with exit code 0

    上面这些一切都是很美好,直到遇到了int*做入参的函数,即即使入参又是出参。在c程序中因为没有引用,想传一个地址,并且这个地址的值在函数内被修改,就比较喜欢用指针。

        def DCGetRetCode(self, handle, icode):
            try:
                self.dll.DCGetRetCode.restype = ctypes.c_bool
                self.dll.DCGetRetCode.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
                # self.bcc.DCGetRetCode.argtype = ctypes.c_void_p
                code = icode
                code = ctypes.c_int()
                b = pointer(code)   # b是code的地址
    
                bRet = self.dll.DCGetRetCode(ctypes.c_void_p(handle), byref(code))
    
                '''
                    self.dll.DCGetRetCode(ctypes.c_void_p(handle), ctypes.pointer(code))
                    用这种方式返回的code不是具体的int数值,而是c_long(100),在数值外面有c_long
                    code.value的值居然是0,醉了 百思不得其解 网上查到到用value都能得到类型里面的值 但这里就是不行
                    byref表示传引用 返回值b[0]就是取指针地址值
                '''
                return bret, b[0]
            except Exception as e:
                print(e)

    调这个函数方法如下

    code = -1
    bret, code = hdll.DCGetRetCode(handle, code)

    如果是c++类库的话,就得另想办法。

  • 相关阅读:
    Linux-read 命令(20)
    47.Linux-DEVICE_ATTR()介绍及使用示例
    46.Linux-创建rc红外遥控平台设备,实现重复功能(2)
    46.Linux-分析rc红外遥控平台驱动框架,修改内核的NEC解码函数BUG(1)
    Xcode定位光标到行首行尾
    Mac 教程:OS X「剪切」移动文件的三种方法
    iOS Xcode最新真机调试包 DeviceSupport
    Flex布局做出自适应页面--语法和案例
    如何使用Android Studio与夜神模拟器开发调试
    Android源代码下载与编译
  • 原文地址:https://www.cnblogs.com/ikel/p/13810375.html
Copyright © 2020-2023  润新知