python怎么调用c的动态链接库

 我来答
龙氏风采
2016-12-27 · 知道合伙人互联网行家
龙氏风采
知道合伙人互联网行家
采纳数:5849 获赞数:12817
从事互联网运营推广,5年以上互联网运营推广经验,丰富的实战经

向TA提问 私信TA
展开全部
  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中创建),头文件:
  [cpp] view plain copy 在CODE上查看代码片派生到我的代码片//hello.h
  #ifdef EXPORT_HELLO_DLL
  #define HELLO_API __declspec(dllexport)
  #else
  #define HELLO_API __declspec(dllimport)
  #endif
  extern "C"
  {
  HELLO_API int IntAdd(int , int);
  }
  CPP文件:
  [cpp] view plain copy 在CODE上查看代码片派生到我的代码片//hello.cpp
  #define EXPORT_HELLO_DLL
  #include "hello.h"
  HELLO_API int IntAdd(int a, int b)
  {
  return a + b;
  }
  这里有两个注意点:
  (1)弄清楚编译的时候函数的调用约定采用的__cdecl还是__stdcall,因为根据DLL中函数调用约定方式,Python将使用相应的函数加载DLL。
  (2)如果采用C++的工程,那么导出的接口需要extern "C",这样python中才能识别导出的函数。
  我的工程中采用__cdecl函数调用约定方式进行编译链接产生hello.dll,然后Python中采用ctypes库对hello.dll进行加载和函数调用:
  [python] view plain copy 在CODE上查看代码片派生到我的代码片from ctypes import *
  dll = cdll.LoadLibrary('hello.dll');
  ret = dll.IntAdd(2, 4);
  print ret;
  OK,一个小例子已经完成了,如果你感兴趣,但还没试过,那就尝试一下吧。
  示例二
  示例一只是一个"hello world"级别的程序,实际运用中更多的需要传递数据结构、字符串等,才能满足我们的需求。那么这个示例将展示,如何传递数据结构参数,以及如何通过数据结构获取返回值。
  首先编写DLL工程中的头文件:
  [cpp] view plain copy 在CODE上查看代码片派生到我的代码片//hello.h
  #ifdef EXPORT_HELLO_DLL
  #define HELLO_API __declspec(dllexport)
  #else
  #define HELLO_API __declspec(dllimport)
  #endif
  #define ARRAY_NUMBER 20
  #define STR_LEN 20
  struct StructTest
  {
  int number;
  char* pChar;
  char str[STR_LEN];
  int iArray[ARRAY_NUMBER];
  };
  extern "C"
  {
  //HELLO_API int IntAdd(int , int);
  HELLO_API char* GetStructInfo(struct StructTest* pStruct);}
  CPP文件如下:
  [cpp] view plain copy 在CODE上查看代码片派生到我的代码片//hello.cpp
  #include <string.h>
  #define EXPORT_HELLO_DLL
  #include "hello.h"
  HELLO_API char* GetStructInfo(struct StructTest* pStruct){
  for (int i = 0; i < ARRAY_NUMBER; i++)
  pStruct->iArray[i] = i;
  pStruct->pChar = "hello python!";
  strcpy (pStruct->str, "hello world!");
  pStruct->number = 100;
  return "just OK";
  }
  GetStructInfo这个函数通过传递一个StructTest类型的指针,然后对对象中的属性进行赋值,最后返回"just OK".
  编写Python调用代码如下,首先在Python中继承Structure构造一个和C DLL中一致的数据结构StructTest,然后设置函数GetStructInfo的参数类型和返回值类型,最后创建一个StructTest对象,并将其转化为指针作为参数,调用函数GetStrcutInfo,最后通过输出数据结构的值来检查是否调用成功:
  [python] view plain copy 在CODE上查看代码片派生到我的代码片from ctypes import *
  ARRAY_NUMBER = 20;
  STR_LEN = 20;
  #define type
  INTARRAY20 = c_int * ARRAY_NUMBER;
  CHARARRAY20 = c_char * STR_LEN;
  #define struct
  class StructTest(Structure):
  _fields_ = [
  ("number", c_int),
  ("pChar", c_char_p),
  ("str", CHARARRAY20),
  ("iArray", INTARRAY20)
  ]
  #load dll and get the function object
  dll = cdll.LoadLibrary('hello.dll');
  GetStructInfo = dll.GetStructInfo;
  #set the return type
  GetStructInfo.restype = c_char_p;
  #set the argtypes
  GetStructInfo.argtypes = [POINTER(StructTest)];objectStruct = StructTest();
  #invoke api GetStructInfo
  retStr = GetStructInfo(byref(objectStruct));#check result
  print "number: ", objectStruct.number;
  print "pChar: ", objectStruct.pChar;
  print "str: ", objectStruct.str;
  for i,val in enumerate(objectStruct.iArray):
  print 'Array[i]: ', val;
  print retStr;
  总结
  1. 用64位的Python去加载32位的DLL会出错
  2. 以上只是些测试程序,在编写Python过程中尽可能的使用"try Except"来处理异常3. 注意在Python与C DLL交互的时候字节对齐问题4. ctypes库的功能还有待继续探索
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式