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++类库的话,就得另想办法。

原文地址:https://www.cnblogs.com/ikel/p/13810375.html