python結構體ctypes,python 基本結構

本文目錄一覽:

python怎麼導入ctypes

1. 載入Windows系統自帶的dll文件:

#載入cdecl調用約定的dll

msvcrt =cdll.msvcrt

#載入stdcall調用約定的dll

kernel32 =windll.kernel32

2. 載入自己dll文件,假如為addFuncDll,方式如下:

mydll =CDLL(“addFuncDll.dll”)

或者 mydll = cdll.addFuncDll

如果其中有函數add,計算兩個整數的和,則使用方式如下:

result=mydll.add(4,5)

可以多一步指明add函數的參數類型(也可不指明):

mydll.add.argtypes= [c_int,c_int]

3. 結構體在python中定義為Structure的子類如下:

class POINT(Structure):

_fields_ = [(“x”, c_int),

(“y”,c_int)]

_fields中每一項為元組(成員名稱,類型)

結構體還可以用於其他的結構體:

class RECT(Structure):

_fields_ = [(“upperleft”,POINT),

(“lowerright”,POINT)]

python 是否有能列出動態鏈接庫中有哪些方法的庫

最近看了《Gray hat python》一書,這才知道為什麼python是黑客必學的編程語言。通過python的ctypes模塊,可以直接調用動態鏈接庫中的導出函數,而且甚至可以直接在python中構建出複雜的C結構體!!!使得python也具備了底層內存操作的能力,再配合python本身強大的表達能力,能不讓人激動么。

之前為了在python中調用動態鏈接庫導出的函數,你需要自行解析出這些導出函數的地址。而現在ctypes庫會替我們完成這個麻煩的過程,大大方便了我們直接在python中調用C函數的能力。

ctypes模塊中有三種不同的動態鏈接庫載入方式:cdll, windll, oledll。不同之處在於鏈接庫中的函數所遵從的函數調用方式(calling convention)以及返回方式有所不同。

cdll用於載入遵循cdecl標準函數調用約定的鏈接庫。windll則用於載入遵循stdcall調用約定的動態鏈接庫。oledll與windll完全相同,只是會默認其載入的函數會統一返回一個Windows HRESULT錯誤編碼。

先複習一下有關函數調用約定的知識:函數調用約定指的是函數參數入棧的順序、哪些參數入棧、哪些通過寄存器傳值、函數返回時棧幀的回收方式(是由調用者負責清理,還是被調用者清理)、函數名稱的修飾方法等等。基本上我們最常見的調用約定就是cdecl和stdcall兩種。在《程序員的自我修養–鏈接、裝載與庫》一書的第10章有對函數調用約定的更詳細介紹。

cdecl規定函數參數列表以從右到左的方式入棧,且由函數的調用者負責清除棧幀上的參數。stdcall的參數入棧方式與cdecl一致,但函數返回時是由被調用者自己負責清理棧幀。而且stdcall是Win32 API函數所使用的調用約定。OK,就這麼多,夠了。

測試一下在Linux平台和Windows平台下通過ctypes模塊導入C庫中函數的小例子:

Windows 下:

from ctypes import *

msvcrt = cdll.msvcrt

msg = “Hello world!\n”

msvcrt.printf(“Testing: %s”, msg)

Linux下:

from ctypes import *

libc = CDLL(“libc.so.6”)

msg = “Hello, world!\n”

libc.printf(“Testing: %s”, msg)

可以看到動態鏈接庫中的printf被直接導入到python中來調用了。

那麼,在python中怎麼表示C的類型?不用擔心,下面這張表就能搞定。

有了這個映射關係,多複雜的C類型也能在python中表達出來。

在C中定義一個聯合:

union

{

long barley_long;

int barley_int;

char barley_char[8];

}barley_amount;

而在python中同等的定義為:注意一下python中定義數組的方式。

class barley_amount(Union):

_fields_ = [

(“barley_long”, c_long),

(“barley_int”, c_int),

(“barley_char”, c_char * 8),

]

測試一下這個例子,在python中定義一個聯合體,為其賦值,再分別訪問其成員。

from ctypes import *

class barley_amount(Union):

_fields_ = [

(“barley_long”, c_long),

(“barley_int”, c_int),

(“barley_char”, c_char * 8),

]

value = raw_input(“Enter the amount of barley to put into the beer vat:”)

my_barley = barley_amount(int(value))

print “Barley amount as a long: %ld” % my_barley.barley_long

print “Barley amount as an int: %d” % my_barley.barley_int

print “Barley amount as a char: %s” % my_barley.barley_char

python ctypes 怎麼處理函數返回的一般指針

test.c(動態庫源代碼)

[cpp] view plain copy

// 編譯生成動態庫: gcc -g -fPIC -shared -o libtest.so test.c

#include stdio.h

#include string.h

#include stdlib.h

typedef struct StructPointerTest

{

char name[20];

int age;

}StructPointerTest, *StructPointer;

StructPointer test() // 返回結構體指針

{

StructPointer p = (StructPointer)malloc(sizeof(StructPointerTest));

strcpy(p-name, “Joe”);

p-age = 20;

return p;

}

編譯:gcc -g -fPIC -shared -o libtest.so test.c

call.py(python調用C語言生成的動態庫):

[python] view plain copy

#!/bin/env python

# coding=UTF-8

from ctypes import *

#python中結構體定義

class StructPointer(Structure):

_fields_ = [(“name”, c_char * 20), (“age”, c_int)]

if __name__ == “__main__”:

lib = cdll.LoadLibrary(“./libtest.so”)

lib.test.restype = POINTER(StructPointer)

p = lib.test()

print “%s: %d” %(p.contents.name, p.contents.age)

最後運行結果:

[plain] view plain copy

[zcm@c_py #112]$make clean

rm -f *.o libtest.so

[zcm@c_py #113]$make

gcc -g -fPIC -shared -o libtest.so test.c

[zcm@c_py #114]$./call.py

Joe: 20

[zcm@c_py #115]$

關於python ctypes里 Union的問題

DataValue(Structure):

_anonymous_ = (‘DataValue’,)

可能是寫錯了,改成:

class DataValue(Structure):

_anonymous_ = (‘DataValue’,)

data_value.DataValue = 23

這句報錯嗎?

換成:

data_value.i4Val = 32

試試

如果有問題,希望你把錯誤的原因(traceback)貼出來

Python 外部函數調用庫ctypes簡介

一直對不同語言間的交互感興趣,python和C語言又深有淵源,所以對python和c語言交互產生了興趣。

最近了解了python提供的一個外部函數庫 ctypes , 它提供了C語言兼容的幾種數據類型,並且可以允許調用C編譯好的庫。

這裡是閱讀相關資料的一個記錄,內容大部分來自 官方文檔 。

ctypes 提供了一些原始的C語言兼容的數據類型,參見下表,其中第一列是在ctypes庫中定義的變數類型,第二列是C語言定義的變數類型,第三列是Python語言在不使用ctypes時定義的變數類型。

創建簡單的ctypes類型如下:

使用 .value 訪問和改變值:

改變指針類型的變數值:

如果需要直接操作內存地址的數據類型:

下面的例子演示了使用C的數組和結構體:

創建指針實例

使用cast()類型轉換

類似於C語言定義函數時,會先定義返回類型,然後具體實現再定義,當遇到下面這種情況時,也需要這麼干:

可以簡單地將”so”和”dll”理解成Linux和windows上動態鏈接庫的指代,這裡我們以Linux為例。注意,ctypes提供的介面會在不同系統上有出入,比如為了載入動態鏈接庫, 在Linux上提供的是 cdll , 而在Windows上提供的是 windll 和 oledll 。

ctypes會尋找 _as_paramter_ 屬性來用作調用函數的參數傳入,這樣就可以傳入自己定義的類作為參數,示例如下:

用 argtypes 和 restype 來指定調用的函數返回類型。

這裡我只是列出了 ctypes 最基礎的部分,還有很多細節請參考官方文檔。

這兩天文章沒有寫,先是早出晚歸出去玩了一整天,然後加班到凌晨3點左右,一天一篇計劃划水得嚴重啊…

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/288903.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-12-24 03:01
下一篇 2024-12-24 03:01

相關推薦

  • 如何查看Anaconda中Python路徑

    對Anaconda中Python路徑即conda環境的查看進行詳細的闡述。 一、使用命令行查看 1、在Windows系統中,可以使用命令提示符(cmd)或者Anaconda Pro…

    編程 2025-04-29
  • Python中引入上一級目錄中函數

    Python中經常需要調用其他文件夾中的模塊或函數,其中一個常見的操作是引入上一級目錄中的函數。在此,我們將從多個角度詳細解釋如何在Python中引入上一級目錄的函數。 一、加入環…

    編程 2025-04-29
  • Python列表中負數的個數

    Python列表是一個有序的集合,可以存儲多個不同類型的元素。而負數是指小於0的整數。在Python列表中,我們想要找到負數的個數,可以通過以下幾個方面進行實現。 一、使用循環遍歷…

    編程 2025-04-29
  • Python計算陽曆日期對應周幾

    本文介紹如何通過Python計算任意陽曆日期對應周幾。 一、獲取日期 獲取日期可以通過Python內置的模塊datetime實現,示例代碼如下: from datetime imp…

    編程 2025-04-29
  • Python周杰倫代碼用法介紹

    本文將從多個方面對Python周杰倫代碼進行詳細的闡述。 一、代碼介紹 from urllib.request import urlopen from bs4 import Bea…

    編程 2025-04-29
  • Python程序需要編譯才能執行

    Python 被廣泛應用於數據分析、人工智慧、科學計算等領域,它的靈活性和簡單易學的性質使得越來越多的人喜歡使用 Python 進行編程。然而,在 Python 中程序執行的方式不…

    編程 2025-04-29
  • Python清華鏡像下載

    Python清華鏡像是一個高質量的Python開發資源鏡像站,提供了Python及其相關的開發工具、框架和文檔的下載服務。本文將從以下幾個方面對Python清華鏡像下載進行詳細的闡…

    編程 2025-04-29
  • Python字典去重複工具

    使用Python語言編寫字典去重複工具,可幫助用戶快速去重複。 一、字典去重複工具的需求 在使用Python編寫程序時,我們經常需要處理數據文件,其中包含了大量的重複數據。為了方便…

    編程 2025-04-29
  • python強行終止程序快捷鍵

    本文將從多個方面對python強行終止程序快捷鍵進行詳細闡述,並提供相應代碼示例。 一、Ctrl+C快捷鍵 Ctrl+C快捷鍵是在終端中經常用來強行終止運行的程序。當你在終端中運行…

    編程 2025-04-29
  • 蝴蝶優化演算法Python版

    蝴蝶優化演算法是一種基於仿生學的優化演算法,模仿自然界中的蝴蝶進行搜索。它可以應用於多個領域的優化問題,包括數學優化、工程問題、機器學習等。本文將從多個方面對蝴蝶優化演算法Python版…

    編程 2025-04-29

發表回復

登錄後才能評論