Python的學習(十五)---- 呼叫windows下DLL詳解

linda1000發表於2012-11-27

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來啟動程式等

摘自  http://wenku.baidu.com/view/954b18333968011ca300917e.html

相關文章