日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關咨詢
選擇下列產品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關閉右側工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
厲害了,Python也能使用動態(tài)鏈接庫

創(chuàng)新互聯(lián)建站是一家專注于成都網(wǎng)站制作、成都網(wǎng)站建設與策劃設計,定興網(wǎng)站建設哪家好?創(chuàng)新互聯(lián)建站做網(wǎng)站,專注于網(wǎng)站建設10年,網(wǎng)設計領域的專業(yè)建站公司;建站業(yè)務涵蓋:定興等地區(qū)。定興做網(wǎng)站價格咨詢:13518219792

一、神秘的模塊

我們都知道C語言是比較靠近底層的語言,所以我們要想使用動態(tài)鏈接庫就要給Python和C構建一座橋梁。今天我們要說的這座橋梁就是---Ctypes。

二、安裝并導入Ctypes

系統(tǒng)自帶有該模塊,若沒有,安裝Pywin32也就有了。

from ctypes import *

三、認識動態(tài)鏈接庫

動態(tài)鏈接庫在linux 系統(tǒng)中表現(xiàn)為“.so”的后綴文件,而在Windows中表現(xiàn)為”.dll“的后綴文件。

四、初步了解Ctypes

安裝好后我們需要對Ctypes做一個大致的了解,首先我們得先查看它的所有函數(shù)及其方法。

接下來我們就將對這些方法做一個簡單的了解,并且配上一個小實例讓大家看了之后更容易懂,讓天底下不再有十分艱難的編程問題存在是我們的宗旨。

五、Ctypes的基本用法

1. 數(shù)據(jù)類型

Ctypes很完美的契合了C的數(shù)據(jù)類型,豐富多樣,下面我們來看看吧:

我們可以看到這些都是可以在Python中使用的C語言數(shù)據(jù)類型。我們一起來看看它的用處吧:

我們可以看到這些基本就是數(shù)據(jù)類型的使用方法了,也是挺簡單的。

2. 操作變量

剛剛我們定義了許多類型的變量,下面我們像使用C語言變量一樣來使用它們。

(1) 訪問變量的值

it.value

(2) 修改變量的值

it.value=43  #直接賦值,即可修改

(3) 給變量添加指針

#強指針
pt=pointer(it) pointer(c_int(10)) #定義指針,指向變量 pt,pt是指針內存地址
pt.contents #指針所指的對象
#弱指針 比強指針速度快
byref(it,4) #it:c的實例 4:偏移量
#返回一個指針的圖片來做一個C實例,只可用作為函數(shù)參數(shù)

上面的指針只是簡單的創(chuàng)建了指針實例,還有一種方法可以指定指針類型,然后進行創(chuàng)建:

aa=POINTER(c_int) #創(chuàng)建指針
aa(c_int(43)) #創(chuàng)建指針實例
aa(c_int(43)).contents.value#獲取指針的值

也可以創(chuàng)建一個空指針:

POINTER(c_int)() #創(chuàng)建空指針,空指針是一個bool值

可以看出空指針沒有Contents屬性。

也可以使用抽象基類“_Pointer”來完成指針的操作:

import ctypes
class ss(ctypes._Pointer): #這里必須帶上ctypes,否則會報錯
_type_=c_int
contents=c_float
aa=ss(c_int(10)) #指定對象類型為整形
print(aa.contents) #替換為浮點類型

3. 創(chuàng)建修改緩沖

Ctypes定義的指針類型是不可以修改的,如果需要在C函數(shù)中被修改,需要使用一些函數(shù)來修改,下面來看看:

(1) 字符緩沖

p=create_string_buffer(4)           #創(chuàng)建一個4字節(jié)緩沖區(qū) 初始化為空字節(jié)
create_string_buffer(b"Hello") #創(chuàng)建一個包含空字符結尾字符串緩沖區(qū)
create_string_buffer(b"Hello", 10) #創(chuàng)建一個10字節(jié)緩沖區(qū)
print(sizeof(p),repr(p.raw)) #內存塊大小 字節(jié)信息

(2) unicode緩沖

a=create_unicode_buffer(5)  #創(chuàng)建一個10字節(jié)的unicode字符緩沖區(qū)
create_unicode_buffer('ffsa')
create_unicode_buffer('ffsa',5) #結尾空字符
print(sizeof(a)) #內存塊大小

4. 調用動態(tài)鏈接庫

動態(tài)鏈接庫的調用方法很多,任你挑選。

CDLL(xx.dll)
OleDLL(xx.dll)
PyDLL(xx.dll)
WinDLL(xx.dll)
cdll.LoadLibrary(xx.dll)
oledll.LoadLibrary(xx.dll)
pydll.LoadLibrary(xx.dll)
windll.LoadLibrary(xx.dll)
#也可使用鏈接庫讀取器LibraryLoader,它也同樣支持上面的八種方式
LibraryLoader(CDLL('C:\\Windows\\System32\\user32.dll'))
LibraryLoader(cdll.LoadLibrary('C:\\Windows\\System32\\user32.dll'))

綜上所述,調用動態(tài)鏈接庫的方法共有16種之多。

5. 查找動態(tài)鏈接庫

from ctypes.util import find_library
find_library('user32')# 查找

6. 調用動態(tài)鏈接庫函數(shù)

dll=windll.LoadLibrary(xx.dll)
dll.函數(shù)名

7. Windows Api函數(shù)

所有的Window Api 函數(shù)都包含在Dll中,其中有幾個非常重要的Dll:

kernel32.dll    #用于管理內存、進程和線程的各個函數(shù)
user32.dll #用于創(chuàng)建用戶界面的各個函數(shù)
gdi32.dll #用于畫圖和顯示文本的各個函數(shù)
advapi32.dll #用于操作注冊表、系統(tǒng)終止與重啟、Windows服務啟動/停止/創(chuàng)建、賬戶管理的各個函數(shù)
shell32.dll #用于訪問操作系統(tǒng)shell提供的功能
netapi32.dll #用于訪問操作系統(tǒng)提供的各種通信功能
comctl32.dll #用于訪問操作系統(tǒng)的狀態(tài)條、進度條、工具條等功能
comdlg32.dll #用于管理文件打開、文件保存、顏色字體選擇等標準對話框

#調用這些dll非常簡單:
windll.gdi32 #即可

8. 獲取模塊頭

windll.kernel32#同時導出同一個函數(shù)的ANSI版本(GetModuleHandleA)和UNICODE版(GetModuleHandleW)
windll.kernel32.GetModuleHandleA(0) #里面只允許有0或者None,其它會報錯
windll.kernel32.GetModuleHandleW()

9. Dll基本信息獲取

當我們讀取Dll后有時候需要對它的路徑或者句柄進行操作,這個時候我們需要獲取這些參數(shù):

(1) 獲取窗口句柄

dll._handle

(2) 獲取Dll絕對路徑

dll._name

10. 調用Python中的Os模塊中的所有方法

這個自是不必說,與Os模塊密切相關。

os=ctypes._os
os.getcwd()

11. 打印字符長度

windll.msvcrt.printf(b'fsfs') #不支持中文輸出 輸出為4
windll.msvcrt.printf('fsfs') #輸出為2
#以下情況與上相同
cdll.msvcrt.printf('fsfs')
pydll.msvcrt.printf('fsfs')
oledll.msvcrt.printf('fsfs')

12. 獲取C實例內部緩沖區(qū)地址

addressof(c_int(30))

13. 判斷是否有管理員權限

windll.shell32.IsUserAnAdmin()
cdll.shell32.IsUserAnAdmin()
pydll.shell32.IsUserAnAdmin()
oledll.shell32.IsUserAnAdmin()
#結果返回1則表示有,否則無

通過判斷當前用戶是否為管理員用戶后,我可以進行下一步操作,如果是則打開瀏覽器,如果不是則嘗試打開:

import ctypes, sys
def admin():
try:
aa=ctypes.windll.shell32.IsUserAnAdmin()
except:
return
finally:
return aa
if admin()==1:
os.popen(r'E:\360browser\360se6\Application\360se.exe')
else:
if sys.version_info[0] == 3:
ctypes.windll.shell32.ShellExecuteW(0, "runas", sys.executable,'',__file__,0)
else:
print('版本太低,不支持2.0')

#sys.executable:python主程序的絕對路徑
#__file__:當前程序的絕對路徑

14. 讓鼠標鍵盤失靈

aa=cdll.LoadLibrary('C:\\Windows\\System32\\user32.dll')
aa.BlockInput(True)#鍵盤鼠標被鎖定
time.sleep(5) # 鎖定五秒
aa.BlockInput(False) #被釋放

15. 打開文件或者應用程序

aa=windll.shell32.ShellExecuteW(0,'open','C:\\Windows\\System32\\notepad.exe','',os.path.join(os.path.dirname(__file__),'OSI.txt'),0)
#參數(shù)1:父窗口的句柄,如果沒有父窗口,則為0
#參數(shù)2:要運行的操作,如:runas,open,print
#參數(shù)3:要運行的程序絕對路徑
#參數(shù)4:給程序傳遞的參數(shù),如果打開的是文件則為空
#參數(shù)5:要打開的文件的絕對路徑
#參數(shù)6:是否顯示窗口 0:后臺打開 1:前臺打開
#如果aa返回值小于32則表示打開失敗
aa.bit_length()#指定數(shù)值的二進制的長度數(shù)、寬度數(shù)

16. 結構體和聯(lián)合體

要想使用必須從Structure 和 Union 繼承,子類必須定義,F(xiàn)ields 屬性,F(xiàn)ields屬性必須是一個二元組的列表。

元祖中第一個是變量名,第二個是數(shù)據(jù)類型,可以是Ctypes任意一種變量類型。

(1) 結構體Structure

也可以一次性傳遞多個不同數(shù)據(jù)類型的參數(shù):

(2) 聯(lián)合體Union

它和結構體的使用方法一樣,但是結果不同,下面我們來看下:

造成這一區(qū)別的原因聯(lián)合體所有成員變量共用一塊內存,可以內存復用;而結構體,每個成員變量占用一塊內存。

17. 數(shù)組操作

ARRAY(type,len) #前者是Ctypes的某個類型的值,而后者是值的長度,返回一個值與長度的乘積
Array(*args) #它是一個數(shù)組抽象基類, 我們可以重寫它來進行使用,
class cx(Array):
_length_=100 #重寫方法_length_(數(shù)組中元素的數(shù)量)
_type_=c_int #指定數(shù)組中每個元素的類型(整形)
aa=cx(12,32,43,324,54,4,32,34,52434)
print(aa[2],aa[5:7]) #利用下標或者切片訪問

18. 改變對象的內存緩沖區(qū)大小

Ctypes可以重新設置對象的內存緩沖區(qū)大?。?/p>

可以看到,此時的同一個對象內存緩沖區(qū)大小不一樣.

19. 轉換指向不同數(shù)據(jù)類型的指針

這里我們用到了一個神器的函數(shù)“Cast”,它可以將不同的數(shù)據(jù)類型的指針進行轉換。

class bb(Structure):
_fields_ = [("val", POINTER(c_int))]
b=bb()
b.val=cast((c_float*4)(1.2,3.2,4.3),POINTER(c_int))
print(b.val[1])

20. 進程操作

aa=0x00000020 #定義正常優(yōu)先級的類
ker=windll.LoadLibrary('kernel32.dll') #加載動態(tài)鏈接庫
crk=ker.CreateProcessA #獲得創(chuàng)建后的進程的函數(shù)地址
rk=ker.ReadProcessMemory #獲得讀取進程內存的函數(shù)地址
wk=ker.WriteProcessMemory #獲得寫入進程內存的函數(shù)地址
ker.TerminateProcess #終止進程
print(ker,'\n',crk,'\n',rk,'\n',wk)

21. 調用Window系統(tǒng)Api

就以Window 彈框函數(shù)MessageBox為例。

from ctypes import c_int, WINFUNCTYPE, windll
from ctypes.wintypes import HWND, LPCWSTR, UINT
tp = WINFUNCTYPE(c_int, HWND, LPCWSTR, LPCWSTR, UINT) #window函數(shù)類型
bt = (1, "hwnd", 0), (1, "text", "我是內容"), (1, "caption", "我是標題"), (1, "type", 0)
MessageBox =tp(("MessageBoxW", windll.user32),bt) #調用消息彈框函數(shù)
MessageBox()
ab=MessageBox(caption='提示',text="我也是內容") #設置彈框參數(shù)
aa=MessageBox(caption='警告',type=2,text="是否進入?")
if aa==3: #判斷輸出類型
print('終止操作')
if aa==4:
print('重試')
if aa==5:
print('忽略')

可以看到當我選擇了中止之后它便提示終止操作。其實還有一種類似的方法:

注:這里彈窗的參數(shù)均不支持中文,務必按我上面的格式寫,不然會出錯。

22. 獲取Windows窗口中的所有頂層窗口的值


from ctypes import *
from ctypes import wintypes
#定義回調函數(shù)類型
res= WINFUNCTYPE(wintypes.BOOL,wintypes.HWND, wintypes.LPARAM)
def win(h,p):#實現(xiàn)回調函數(shù)功能,函數(shù)為bool類型;h:頂層窗口的句柄 p:應用程序定義的一個值,
le= user32.GetWindowTextLengthW(h)+1 #獲取window文本長度,加1可獲取完整的信息
buffer = create_unicode_buffer(le) #創(chuàng)建緩沖
user32.GetWindowTextW(h, buffer, le) #獲取window文本
print(buffer.value) #獲取緩沖區(qū)中的信息
return True
user32 = windll.LoadLibrary('user32.dll')#加載dll
user32.EnumWindows(res(win), 0) #枚舉頂層窗口,不列舉子窗口

六、總結

Ctypes總的來說還是蠻不錯的,挺適合C語言小白學習,畢竟Api的確太多太復雜了,還是Python友好點。


當前標題:厲害了,Python也能使用動態(tài)鏈接庫
網(wǎng)頁網(wǎng)址:http://www.5511xx.com/article/coccoeh.html