[Python] Python 調用 C 共用庫

來源:互聯網
上載者:User

標籤:style   blog   http   color   使用   os   io   檔案   

  Linux/Unix 平台下共用庫(Shared Library)檔案尾碼 .so;在 Windows 平台稱為動態連結程式庫(Dynamic Link Library),檔案名稱尾碼為 .dll。

 

 

利用 ctypes 模組調用 C 共用庫

 

  ctypes 是 Python 標準庫提供的一個模組,Python 2.3 版本以上支援該模組。ctypes 是 Python 進階外部函數介面,Python 通過它可以調用 C 語言編譯的靜態連結庫和動態連結程式庫。ctypes 支援多個平台,包括 Windows, Windows CE, Mac OS X, Linux, Solaris, FreeBSD, OpenBSD。

 

  ctypes 模組定義了一些基礎 C 相容資料類型,具體類型請點擊此處查看。

 

  以下執行個體示範如何在 Python 程式中使用 ctypes 模組來調用 C 程式函數。

 

1. 準備 C 程式源檔案 sum.c

 

  在 sum.c 源檔案定義一個 sum() 函數,用以計算 N 個連續自然數之和。

#include <stdio.h>int main(void){    int x;    printf("Input an integer:\n");    scanf("%d", &x);    printf("sum=%d\n", sum(x));    return 0;};int sum(int x){    int i, result=0;    for(i=0; i<=x; i++){        result+=i;    }    return result;};

 

2. 將 C 原始碼編譯成共用庫檔案 sum.so

 

  使用 gcc 編譯器將 sum.c 編譯為共用庫檔案 sum.so。

$ gcc sum.c -fPIC -shared -o sum.so

 

3. 準備 Python 模組 sum.py

 

  在 sum.py 模組中我們定義一個 py_sum() 函數,該函數是 sum.c 檔案中 sum() 函數的 Python 實現。

#!/usr/bin/env python# -*- coding: utf8 -*-import ctypesso = ctypes.CDLL(‘./sum.so‘)def display_dict():    print "Type of so is %s" % type(so)    print "Attributes before calling so.sum: %s" % dir(so)    print "so.sum(10) = %s" % so.sum(10)    print "Attributes after calling so.sum: %s" % dir(so)def py_sum(x):    y = 0    for i in range(x+1):        y += i    return ydef so_sum(x):    return so.sum(x)if __name__ == "__main__":    pass

 

  在 Python 模組中 import ctypes,然後通過 ctypes.CDLL() 方法匯入共用庫檔案 sum.so,之後就可以直接調用動態庫提供的函數。

  

4. 測試 Python 調用共用庫

 

  讓我們在 __main__ 區塊中調用 display_dict 函數:

if __name__ == "__main__":    display_dict()

 

  運行 sum.py 查看結果:

$ python sum.pyType of so is <class ‘ctypes.CDLL‘>Attributes before calling so.sum: [‘_FuncPtr‘, ‘__class__‘, ‘__delattr__‘, ‘__dict__‘, ‘__doc__‘, ‘__format__‘, ‘__getattr__‘, ‘__getattribute__‘, ‘__getitem__‘, ‘__hash__‘, ‘__init__‘, ‘__module__‘, ‘__new__‘, ‘__reduce__‘, ‘__reduce_ex__‘, ‘__repr__‘, ‘__setattr__‘, ‘__sizeof__‘, ‘__str__‘, ‘__subclasshook__‘, ‘__weakref__‘, ‘_func_flags_‘, ‘_func_restype_‘, ‘_handle‘, ‘_name‘]so.sum(10) = 55Attributes after calling so.sum: [‘_FuncPtr‘, ‘__class__‘, ‘__delattr__‘, ‘__dict__‘, ‘__doc__‘, ‘__format__‘, ‘__getattr__‘, ‘__getattribute__‘, ‘__getitem__‘, ‘__hash__‘, ‘__init__‘, ‘__module__‘, ‘__new__‘, ‘__reduce__‘, ‘__reduce_ex__‘, ‘__repr__‘, ‘__setattr__‘, ‘__sizeof__‘, ‘__str__‘, ‘__subclasshook__‘, ‘__weakref__‘, ‘_func_flags_‘, ‘_func_restype_‘, ‘_handle‘, ‘_name‘, ‘sum‘]

 

  從結果可以發現 .so 共用庫匯入到 .py 模組中得到一個 ctypes.CDLL 對象。調用了 C 函數之後,CDLL 對象會將該函數添加到對象屬性中。(在調用 sum 函數之後,CDLL 對象屬性列表中才包含了 sum 函數。)

 

5. Python 調用共用庫的效能

 

  我們修改一下 sum.py 模組:

if __name__ == "__main__":    import timeit    i = 10000    print "py_sum(%s) = %s" % (i, py_sum(i))    print "so_sum(%s) = %s" % (i, so_sum(i))    print timeit.timeit("py_sum(10000)", setup="from __main__ import py_sum", number=1000)    print timeit.timeit("so_sum(10000)", setup="from __main__ import so_sum", number=1000)

 

  查看運行結果:

$ python sum.pypy_sum(10000) = 50005000so_sum(10000) = 500050006.820616006850.158802986145

 

  以上測試顯示,迴圈疊加 10000 次,執行代碼 1000 次,Python 代碼耗費了 6.820 秒,C 代碼耗費了 0.158 秒,Python 代碼耗費時間是 C 代碼耗費時間的 42.95 倍。

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.