Chinaunix首页 | 论坛 | 博客
  • 博客访问: 47066
  • 博文数量: 23
  • 博客积分: 425
  • 博客等级: 下士
  • 技术积分: 237
  • 用 户 组: 普通用户
  • 注册时间: 2012-12-10 09:57
文章分类

全部博文(23)

文章存档

2013年(23)

我的朋友

分类: Python/Ruby

2013-01-05 19:45:40

Python调用windows下DLL详解

在python中某些时候需要C做效率上的补充,在实际应用中,需要做部分数据的交互。
使用python中的ctypes模块可以很方便调用windows的dll(也包括linux下的so文件),
下面将详细的讲解这个模块,首先介绍一个简单的例子
引入ctypes库  from ctypes import *
假设有一个符合cdecl调用约定的DLL文件,且其中包含一个导出函数Add.
from ctypes import *
dll = CDLL("add.dll")
print dll.Add(1, 102)
结果 103

1. 加载DLL
加载的时候要根据你将要调用的函数是符合什么调用约定的
stdcall调用约定: 两种加载方式
Objdll = ctypes.windll.LoadLibrary("dllpath")
Objdll = ctypes.WinDLL("dllpath")
cdesl调用约定: 两种加载方式
Objdll = ctypes.cdll.LoadLibrary("dllpath")
Objdll = ctypes.CDLL("dllpath")
其实 windll 和 cdll 分别是WinDLL类和CDLL类的对象

2. 调用dll 中的方法
在1中加载dll的时候会返回一个DLL对象,利用该对象就可以调用dll中的方法


3. C基本类型和ctypes中实现的类型映射表
ctypes 数据类型    C 数据类型
c_char                   char
c_short                  short
c_int                      int
c_long                   long
c_ulong                 unsign long
c_float                   float
c_double               double
c_void_p                void
对应的指针类型是在后面加上"_p”, 如int * 是 c_int_p
在python中要实现c语言中的结构,需要用到类

4. DLL中的函数返回一个指针
虽然这不是一个好的编程方法,不过这种情况的处理方法也很简单,其实返回的都是地址,
把他们转换相应的python类型,在通过value属性访问
pchar = dll.getbuffer()
szbuffer = c_char_p(pchar)
print szbuffer.value

5. 处理C中的结构体类型
在python里面申明一个类似C的结构体,要用到类,并且这个类必须继承自Structure,先看个简单的例子
C里面dll的定义如下:
typedef struct _SimpleStruct
{ int nNo;
   float fVirus;
   char szBuffer[512];
}SimpleStruct, *PSimpleStruct;

typedef const SimpleStruct *PCSimpleStruct;
extern "C" int _declspec(dllexport) PrintStruct(PSimpleStruct simp);
int PrintStruct(PSimpleStruct simp)
{  print ("nMaxNume = %f, szConten=%s", simp->fVirus, simp->szBuffer);
    return simp->nNo;
}
Python 的定义:
from ctypes import *
class SimpStruct(Structure):
    _fields_ = [ ("nNo", c_int),
                       ("fVirus", c_float),
                       ("szBuffer", c_char*512)]
dll = CDLL("AddDll.dll")
simple = SimpStruct();
simple.nNo = 16
simple.fVirus = 3.1415926
simple.szBuffer = "magicTong\0"
print dll.PrintStruct(byref(simple))
如果结构体里面有指针,甚至是指向结构体的指针,python里面也有相应的处理方法
C代码如下:
typedef struct
{    char words[10]
} keywords;
typedef struct
{    keywords *kws;
      unsigned int len;
}outStruct;
extern "C" int _declspec(dllexport) test(outStruct *o);
int test(outStruct *o)
{    unsigned int i = 4;
      o-> kws = (keywords *)malloc(sizeof(unsigned char) * 10 * i)
      strcpy(o->kws[0].words, "The First Data");
      strcpy(o->kws[1].words, "The Second Data");
      o->len = i;
      return 1;
}
Python代码如下:
class keywords(Structure):
      _fields_ = [('words', c_char*10)]
class outStruct(Structure):
      _fields_ = [('kws', POINTER(keywords)),
                        ('len', c_int)]
o = outStruct();
dll.test(byref(o));
print o.kws[0].keywords;
print o.kws[1].keywords;
print o.len;

另外,还可以通过调用c++实现的dll来直接调用win32 API,或通过kerel32.dll来启动进程等

摘自 

阅读(856) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~