Python调用C/C++动态链接库

转载 2018年04月16日 12:05:55

Python调用C/C++动态链接库的需求

在自动化测试过程中,难免会遇到语言混合使用的情况,这不,我们也遇到了。初步决定采用Robot Framework作为自动化测试框架后,其支持Java和Python,而Python作为主流的语言,怎么能放弃使用它的机会^_^。 然而产品采用是古老90年代开发的C/S结构,因为古老,当时也没有考虑到对产品的测试进行自动化,Client端并没有预留CLI(Command Line interface)形式的接口,真是雪上加霜啊。

那怎么自动化?采用AutoIT来对客户端界面进行自动化测试?可惜AutoIT对当初开发采用的控件识别不是很好,如果采用控件所在位置来进行控制的方式,又会导致自动化测试并不是很稳定。那么!!!只有自己开发接口了,目前在Client端开发出CLI形式的接口,将其封装为DLL,然后在Robot FrameWork框架中采用Python对DLL进行调用。任务艰巨哪!


Python调用DLL例子


示例一

首先,在创建一个DLL工程(本人是在VS 2005中创建),头文件:

  1. //hello.h  
  2. #ifdef EXPORT_HELLO_DLL  
  3. #define HELLO_API __declspec(dllexport)  
  4. #else  
  5. #define HELLO_API __declspec(dllimport)  
  6. #endif  
  7.   
  8. extern "C"  
  9. {  
  10.     HELLO_API int IntAdd(int , int);  
  11. }  

CPP文件:

  1. //hello.cpp  
  2. #define EXPORT_HELLO_DLL  
  3. #include "hello.h"  
  4.   
  5. HELLO_API int IntAdd(int a, int b)  
  6. {  
  7.     return a + b;  
  8. }  

这里有两个注意点:

(1)弄清楚编译的时候函数的调用约定采用的__cdecl还是__stdcall,因为根据DLL中函数调用约定方式,Python将使用相应的函数加载DLL。

(2)如果采用C++的工程,那么导出的接口需要extern "C",这样python中才能识别导出的函数。

我的工程中采用__cdecl函数调用约定方式进行编译链接产生hello.dll,然后Python中采用ctypes库对hello.dll进行加载和函数调用:

[python] view plain copy
  1. from ctypes import *  
  2. dll = cdll.LoadLibrary('hello.dll');  
  3. ret = dll.IntAdd(24);  
  4. print ret;  

OK,一个小例子已经完成了,如果你感兴趣,但还没试过,那就尝试一下吧。

示例二

示例一只是一个"hello world"级别的程序,实际运用中更多的需要传递数据结构、字符串等,才能满足我们的需求。那么这个示例将展示,如何传递数据结构参数,以及如何通过数据结构获取返回值。

首先编写DLL工程中的头文件:

  1. //hello.h  
  2. #ifdef EXPORT_HELLO_DLL  
  3. #define HELLO_API __declspec(dllexport)  
  4. #else  
  5. #define HELLO_API __declspec(dllimport)  
  6. #endif  
  7.   
  8. #define ARRAY_NUMBER 20  
  9. #define STR_LEN 20  
  10.   
  11. struct StructTest  
  12. {  
  13.     int number;  
  14.     char* pChar;  
  15.     char str[STR_LEN];  
  16.     int iArray[ARRAY_NUMBER];  
  17. };  
  18.   
  19. extern "C"  
  20. {  
  21.     //HELLO_API int IntAdd(int , int);  
  22.     HELLO_API char* GetStructInfo(struct StructTest* pStruct);  
  23. }  

CPP文件如下:

  1. //hello.cpp  
  2. #include <string.h>  
  3. #define EXPORT_HELLO_DLL  
  4. #include "hello.h"  
  5.   
  6. HELLO_API char* GetStructInfo(struct StructTest* pStruct)  
  7. {  
  8.     for (int i = 0; i < ARRAY_NUMBER; i++)  
  9.         pStruct->iArray[i] = i;  
  10.   
  11.     pStruct->pChar = "hello python!";  
  12.   
  13.     strcpy (pStruct->str, "hello world!");  
  14.   
  15.     pStruct->number = 100;  
  16.   
  17.     return "just OK";  
  18. }  

GetStructInfo这个函数通过传递一个StructTest类型的指针,然后对对象中的属性进行赋值,最后返回"just OK".

编写Python调用代码如下,首先在Python中继承Structure构造一个和C DLL中一致的数据结构StructTest,然后设置函数GetStructInfo的参数类型和返回值类型,最后创建一个StructTest对象,并将其转化为指针作为参数,调用函数GetStrcutInfo,最后通过输出数据结构的值来检查是否调用成功

[python] view plain copy
  1. from ctypes import *  
  2.   
  3. ARRAY_NUMBER = 20;  
  4. STR_LEN = 20;  
  5. #define type  
  6. INTARRAY20 = c_int * ARRAY_NUMBER;  
  7. CHARARRAY20 = c_char * STR_LEN;  
  8. #define struct  
  9. class StructTest(Structure):  
  10.     _fields_ = [  
  11.         ("number", c_int),  
  12.         ("pChar", c_char_p),  
  13.         ("str", CHARARRAY20),  
  14.         ("iArray", INTARRAY20)  
  15.                ]  
  16.   
  17. #load dll and get the function object  
  18. dll = cdll.LoadLibrary('hello.dll');  
  19. GetStructInfo = dll.GetStructInfo;  
  20. #set the return type  
  21. GetStructInfo.restype = c_char_p;  
  22. #set the argtypes  
  23. GetStructInfo.argtypes = [POINTER(StructTest)];  
  24.   
  25. objectStruct = StructTest();  
  26. #invoke api GetStructInfo  
  27. retStr = GetStructInfo(byref(objectStruct));  
  28.   
  29. #check result  
  30. print "number: ", objectStruct.number;  
  31. print "pChar: ", objectStruct.pChar;  
  32. print "str: ", objectStruct.str;  
  33. for i,val in enumerate(objectStruct.iArray):  
  34.     print 'Array[i]: ', val;  
  35. print retStr;  

总结

1. 用64位的Python去加载32位的DLL会出错

2. 以上只是些测试程序,在编写Python过程中尽可能的使用"try Except"来处理异常

3. 注意在Python与C DLL交互的时候字节对齐问题

4. ctypes库的功能还有待继续探索

C++动态链接库视频教程(Windows动态链接库)

动态链接库在企业级开发中无处不在,本课程包含Windows动态链接库相关知识点,通过浅显易懂的代码与讲解,让你熟悉掌握动态链接库技术!
  • 2017年12月11日 00:30

ubuntu下python调用C/C++方法之动态链接库

安装boost python调用C/C++的方法有很多,本文使用boost.python。考虑到后期有好多在boost上的开发工作,所以boost一并安装了 具体安装方法可以参考:http://blo...
  • qq_36323886
  • qq_36323886
  • 2017-04-15 22:27:06
  • 228

python中调用动态链接库(C++,DLL)

 1, 动态链接库编译 使用VS2015创建“Win32项目”,选择应用程序类型为“DLL”,创建项目完成后,头文件中: #ifdef EXT_DEC_EXPORTS ...
  • u010736419
  • u010736419
  • 2017-07-04 15:21:22
  • 1239

python 3 调用c/c++ 动态链接库 *.dll

首先,创建动态链接库(一个简单的北斗数据处理接口,为简化处理,实现部分直接返回值),代码如下: #ifndef _pro_header_2014_ #define _pro_header_2014_ ...
  • iceboy314159
  • iceboy314159
  • 2016-11-16 21:44:36
  • 3139

linux 下 python调用c或者c++编写的代码使用案例

  • 2017年09月29日 14:30
  • 14KB
  • 下载

Python调用C语言之如何调用动态链接库

 http://blog.csdn.net/nvidia_inside/article/details/38377421
  • mengjiaoduan
  • mengjiaoduan
  • 2016-10-13 19:56:35
  • 1595

ubuntu14 python 调用C++模块

1.安装pydev sudo yum install python-devel 2.编写C++ 代码 #include int Add(int x, int y) { ...
  • pzhw520hchy
  • pzhw520hchy
  • 2017-06-09 00:25:48
  • 435

Linux使用Python调用C/C++接口

C++头文件 pyExt.h: 01 #ifndef PYEXT_H 02 #define PYEXT_H ...
  • liyuan_669
  • liyuan_669
  • 2014-05-09 08:01:25
  • 1290

[C/C++]Windows动态链接库的创建与调用

一、创建动态链接库 创建Win32项目 文件 - 新建 - 项目 模板 - Visual C++ - Win32,选择Win32项目,填写名称dlldemo 下一步 - 选中DLL - 选中...
  • alex_bean
  • alex_bean
  • 2018-02-23 20:47:37
  • 103

[转]关于C与C++中互相调用动态链接库的问题

这两个月埋首基础课程,忽略了技术的学习。间接就冷落了CSDN了。借这次软件工程作业,重新拾回日志工作。 Normal 0 7.8 磅 0 2 false false false MicrosoftIn...
  • lightyearwp
  • lightyearwp
  • 2010-12-05 22:31:00
  • 5513
收藏助手
不良信息举报
您举报文章:Python调用C/C++动态链接库
举报原因:
原因补充:

(最多只允许输入30个字)