接口测试 使用 Python 测试 DLL/SO 动态链接库接口

wuhao for 郑州软件测试圈 · March 22, 2018 · Last by 阿飞 replied at April 12, 2021 · 3742 hits
本帖已被设为精华帖!

1. 背景与需求

  1. 公司通过提供 C/C++ 语言开发的 DLL/SO 动态链接库,向第三方提供接口服务,需要对此进行测试。
  2. 测试人员普遍不具备 C 语言能力,但可以使用 Python 语言解决问题

2. 基础知识

  1. 动态链接库在 Windows 中为.dll 文件,在 linux 中为.so 文件,使用 C/C++ 进行编写。
  2. 通过 Python 调用 C 语言接口时,可以使用 Python 提供的 ctypes 模块调用 C 接口
  3. ctypes 是一个为 Python 准备的内建函数库。无需安装可直接使用。它提供兼容 C 的数据类型,并允许调用 DLL 或 SO 库中的函数。
  4. 每一个 C 语言的参数,都不能直接使用 Python 直接定义的类型,均需使用 ctypes 提供的类型进行定义

3. 调用方法

1. 使用 Python 加载.so 库文件

from ctypes import *
os.chdir('/home/wuhao/eclipse-workspace/yunhsm_SDK_Test/data/')
sdkPath = os.getcwd()
cur = cdll.LoadLibrary(sdkPath + "/libtestapi.so")
return cur

2. 使用 Python 调用.so 中的方法

self.uiLength = c_int(8)     
self.random = (c_ubyte*self.uiLength.value)()
self.ret_generateRandom = cur.SDF_GenerateRandom(self.uiLength, self.random)
print "ret_generateRandom: " + str(self.ret_generateRandom)

3. 使用 Python 的 ctypes 模块,定义几种 C 中常用数据类型

A = (c_ubyte*8)() 对应 C 中的 unsigned char 类型
B = (c_ubyte*3)(1,2,3) 对应 C 中的 unsigned char 类型
C = c_uint(8) 对应 C 中的 unsigned int 类型
D = c_void_p 对应 C 中的 void 类型

Python 调用 ctypes 数据格式 意义 C 中数据结构
A = (c_ubyte*8)() 用 Python 定义一个长度为 8 的数组,数组中内容默认赋值全 0 对应 C 中的 unsigned char 类型
B = (c_ubyte*3)(1,2,3) 用 Python 定义一个长度为 3 的数组,数组中内容为 1,2,3 对应 C 中的 unsigned char 类型
C = c_uint(8) 定义一个 int 型变量,值为 8 对应 C 中的 unsigned int 类型
D = c_void_p 定义一个 void 型变量 对应 C 中的 void 类型

4. 使用 Python 定义 C 中结构体

  1. C 中结构体
-typedf struct ECCrefPublicKey_st{
unsigned int bits;
unsigned char K[ECCref_MAX_LEN]
}ECCrefPrivateKey
  1. Python 中定义 C 结构体
from ctypes import *
from ctypes import c_ubyte
from ctypes import c_int
class ECCrefPublicKey(Structure):
_fields_ = [("bits", c_uint),
("K", c_ubyte*64)]

5. 使用 Python 传入 C 中结构体类型参数 (传入的实质为结构体的指针)

  1. C 中需传入结构体参数的接口:
int SDF_ExternalVerify_ECC(
    void *hSessionHandle,
    ECCrefPublicKey *pucPublicKey,
)

2.Python 中传入结构体参数的方法:

self.eccPublicKey = ECCrefPublicKey()
self.ret_ExternalVerifyECC = self.cur.SDF_ExternalVerify_ECC(hSessionHandle, byref(self.eccPublicKey))

6. 使用 Python 传入 C 中指针类型参数

  1. C 中需传入指针参数的接口:
int SDF_OpenDevice(void **phDeviceHandle);
  1. Python 中传入指针参数的方法:
self.hDeviceHandle = c_void_p(0)
self.ret_OpenDevice = self.cur.SDF_OpenDevice(byref(self.hDeviceHandle))

3. 总结

目前使用 ctypes 模块和以上数据类型,能够满足工作中对动态链接库的接口测试需求,如果工作中涉及到了新得数据类型,后续也会继续进行补充,希望可以帮到大家。

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 7 条回复 时间 点赞
思寒_seveniruby 将本帖设为了精华贴 22 Mar 17:09

会了 java 学习 c 就很简单了,我最近就在学习 c++😂 ,还是赞楼主的 idea~~~~

swig、boost python 这个都提供了较好的封装;可以搞下

Author only

请问,必须是 C 接口才行吗?
还有就是如何进行链表传参

6Floor has deleted
wuhao #7 · July 17, 2018 Author

恩?能具体说下吗?

wuhao #8 · July 17, 2018 Author
spider 回复

这个库就是调用 c 接口的,链表传参这块儿还没有用到,所以不是特别清楚。
你如果有解决方法了的话也建议在这个帖子下发出来。

simple 专栏文章:[精华帖] 社区历年精华帖分类归总 中提及了此贴 13 Dec 14:44

如果需要调用的接口参数是 c++ 类对象,那 ctypes 需要怎样构造这个参数呢

需要 Sign In 后方可回复, 如果你还没有账号请点击这里 Sign Up