1.Python呼叫C語言之如何呼叫動態連結庫
阿新 • • 發佈:2019-01-23
平時用C&C++和Python比較多,喜歡鼓搗點小玩意兒。之前在《數學之美》這本書裡面看見布隆過濾器這個東西,簡直是爬蟲利器!所以當時用C++寫了一個簡單的,後來封裝成了動態連結庫拿來給爬蟲用。所以就研究了一下怎麼用Ptython呼叫C語言,寫個博文記錄一下!
Python呼叫C語言需要動態連結庫的形式,而Python呼叫動態連結庫則需要ctypes這個模組。
首先我們看看ctypes裡面有些神馬東西,怎麼看呢?當然是神奇的dir()函式。
import ctypes
print '\n'.join(dir(ctypes))
大家可以自己把上面程式碼進去執行檢視。
首先要講的是3個東東,CDLL、windll和oledll。在dir裡面,我們會發現一個奇怪的東西,既有Windll又有WINDLL。免得混淆,索性都看看吧。
嗯,就是這樣,CDLL、windll和oledll是三個Class。而OleDLL和WinDLL是2個type(PS:類,型別,傻傻分不清楚?Google it)
這3個Class的區別是它們呼叫的方法和返回值。CDLL載入的庫是標準C語言的cdecl。windll載入的庫是必須使用stdcall的呼叫約定。oledll和windll差不多,不過會返回一個HRESULT錯誤程式碼,使用COM函式可以獲取具體資訊.(這一坨來自一本叫做《python灰帽子》的書)
最後,看看例項吧。
首先看看CDLL的,就用那個布隆過濾器啦。
Example1:
首先附上DLL程式碼,一個很簡單的布隆過濾器,來自某部落格,被我改了改
#include "stdafx.h" #include <iostream> #include <bitset> #include <string> using namespace std; #define DLLAPI extern "C" _declspec(dllexport) const long MAX= 2<<24; bitset<MAX> bloomset; int seeds[7]={3,7,11,13,31,37,61}; int getHash(char* str,int n) { int result=0; for (int i=0;i<strlen(str);i++) { result=seeds[n]*result+(int)str[i]; if(result > 2<<24) result%=2<<24; } return result; } DLLAPI void Dir() { cout<<"bool isInBloomSet(char* str)"<<endl; cout<<"bool addBloomSet(char* str)"<<endl; } DLLAPI int isInBloomSet(char* str) { for ( int i=0;i<7;i++ ) { int hash=getHash(str,i); if(bloomset[hash]==0) return 0; } return 1; } DLLAPI bool addBloomSet(char* str) { for(int i=0;i<7;i++) { int hash=getHash(str,i); bloomset.set(hash,1); } return true; }
python程式碼
from ctypes import *
dllpath='C:\\Users\\***\\Documents\\Visual Studio 2010\\Projects\\BloomFiliter\\Release\\BloomFiliter.dll'
url=[c_char_p('www.baidu.com'),c_char_p('www.google.com')]
bloom=CDLL(dllpath)
bloom.Dir()
print bloom.addBloomSet(url[0])
print bloom.isInBloomSet(url[0])
print bloom.isInBloomSet(url[1])
print ''
x=raw_input()
Exmaple2:
from ctypes import *
msvcrt = cdll.msvcrt
str = "hahahahah!"
msvcrt.printf("Hello %s\n", str)
x=raw_input()
再看看windll的用法吧,直接調MessageBox牛不牛逼
from ctypes import *;
MessageBox = windll.user32.MessageBoxW
test=c_wchar_p("Great")
title=c_wchar_p("Hello World")
MessageBox(0,test,title, 0)
當然windll可以用LoadLibrary其他符合呼叫約定的DLL,大家可以試試。
OleDLL具體方法一樣,大家有空試試吧。