• 跳至主要導覽
  • 跳至主要內容
  • 跳至主要資訊欄
Office 指南

Office 指南

辦公室工作實用教學

  • Excel
  • Word
  • PowerPoint
  • Windows
  • PowerShell
  • R

Python 以 ctypes 載入 DLL、SO 動態連結函式庫教學與範例

介紹如何在 Python 中使用 ctypes 載入 DLL 與 SO 動態連結函式庫,搭配 C/C++ 語言進行高速計算。


Python 的 ctypes 模組可以用來呼叫外部的函式庫,提供相容於 C 語言的資料型別,開發者可以透過這個模組直接呼叫 DLL 檔案(Windows 平台)或 SO 檔案(macOS 或 Linux 平台)中的函數。以下分別介紹 Windows 平台建立與使用 DLL 檔案、macOS 與 Linux 平台建立與使用 SO 檔案的步驟。

Windows 平台(DLL 檔案)

在 Windows 平台中可將 C/C++ 語言的程式編譯成 DLL 動態連結函式庫,再以 Python 的 ctypes 載入使用。

建立 DLL 動態連結函式庫

若在 Windows 中要建立 DLL 動態連結函式庫,可以使用 Visual Studio 開發環境來建立 DLL 檔案,這部分可以參考 Visual Studio 2019 建立 DLL 動態連結函式庫教學與範例,而在編譯時要注意編譯的版本(32 位元或 64 位元)要跟 Python 的版本相同。

Python 使用 DLL 動態連結函式庫

準備好 MyDLL.dll 這個動態連結函式庫檔案之後,就可以在 Python 中利用 ctypes 載入並呼叫其中的函數了。

from ctypes import cdll, c_double

# 載入 DLL 動態連結函式庫
mydll = cdll.LoadLibrary('./MyDLL.dll')

# 設定 DLL 檔案中 dist 函數的參數資料型態
mydll.dist.argtypes = [c_double, c_double, c_double, c_double]

# 設定 DLL 檔案中 dist 函數的傳回值資料型態
mydll.dist.restype = c_double

# 呼叫 DLL 檔案中的 dist 函數
d = mydll.dist(1.0, 1.0, 4.0, 5.0)
print("dist =", d)
dist = 5.0

macOS 與 Linux 平台(DLL 檔案)

若在 macOS 與 Linux 平台中,則會改用 gcc 或 g++ 將 C/C++ 的程式編譯成 SO 動態連結檔,再以 Python 的 ctypes 載入使用。

建立 SO 動態連結檔案

以 C++ 撰寫一個計算歐氏距離(Euclidean Distance)的函數,原始碼如下:

#include <cmath>

// 計算歐氏距離函數
extern "C" double dist(
  const double x1, const double y1,
  const double x2, const double y2) {
  return std::sqrt(std::pow(x1 - x2, 2) + std::pow(y1 - y2, 2));
}

將這段 C++ 程式碼儲存為 my_so.cpp,並以 g++ 將其編譯成 SO 動態連結檔案:

# 將 C++ 程式編譯成 SO 動態連結檔案
g++ -Wall -Wextra -O -ansi -pedantic -fPIC -shared my_so.cpp -o my_so.so

編譯成功之後,就會產生 my_so.so 這個動態連結檔案。

Python 使用 DLL 動態連結函式庫

準備好 my_so.so 這個動態連結檔案之後,就可以在 Python 中利用 ctypes 載入並呼叫其中的函數了。

from ctypes import cdll, c_double

# 載入 SO 動態連結檔案
mydll = cdll.LoadLibrary('./my_so.so')

# 設定 SO 檔案中 dist 函數的參數資料型態
mydll.dist.argtypes = [c_double, c_double, c_double, c_double]

# 設定 SO 檔案中 dist 函數的傳回值資料型態
mydll.dist.restype = c_double

# 呼叫 SO 檔案中的 dist 函數
d = mydll.dist(1.0, 1.0, 4.0, 5.0)
print("dist =", d)
dist = 5.0

傳遞陣列

若需要在 Python 與 C/C++ 之間傳遞整個陣列的資料,可以使用指標的方式,以下是一個簡單的 SO 動態連結檔案範例。

假設 C++ 的程式碼如下,sort 函數會將傳入的陣列進行排序:

#include <algorithm>
#include <functional>

// 排序函數
extern "C" void sort(
  double array[], const unsigned int size) {
  std::sort(array, array + size, std::less<double>());
}

將這段 C++ 程式碼編譯成 my_so2.so 動態連結檔案之後,在 Python 中使用以下方式傳入 NumPy 陣列即可進行資料的排序。

import numpy as np
from ctypes import cdll, c_double, c_uint, POINTER

# 載入 SO 動態連結檔案
mydll = cdll.LoadLibrary('./my_so2.so')

# 設定 SO 檔案中 sort 函數的參數資料型態
mydll.sort.argtypes = [POINTER(c_double), c_uint]

# 設定 SO 檔案中 sort 函數的傳回值資料型態
mydll.sort.restype = None

# 建立 NumPy 資料陣列
data = np.array([3.2, 5.6, 1.2, 9.4, 7.3])

# 取得陣列的指標
dataPtr = data.ctypes.data_as(POINTER(c_double))

# 呼叫 SO 檔案中的 sort 函數
mydll.sort(dataPtr, data.size)
print(data)
[1.2 3.2 5.6 7.3 9.4]

參考資料:Wolfprojects

分類:Python

讀者互動方式

發佈留言 取消回覆

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

主要資訊欄

搜尋

近期文章

  • C++ 語言使用 Crypto++ 實作 RSA 數位簽章教學與範例
  • C++ 語言使用 Crypto++ 實作 RSA-OAEP 搭配 SHA256 加密教學與範例
  • C++ 語言使用 Crypto++ 實作 AES 加密、解密、認證加密教學與範例
  • C++ 語言使用 Crypto++ 實作 MD5、SHA1、SHA2、BLAKE2 雜湊教學與範例
  • Ubuntu Linux 安裝、使用 Crypto++ 加密函式庫教學與範例
  • C 語言使用 OpenSSL 實作橢圓曲線 ECDH 金鑰交換教學與範例
  • Python 以 eciespy 實作 ECC 非對稱式加密方法教學與範例
  • C 語言使用 OpenSSL 實作 PBKDF2 教學與範例

推薦網站

  • Udemy 線上教學課程
  • Coursera 線上教學課程

關注本站

  • 電子郵件
  • Facebook

公益

  • 家扶基金會
  • 台灣世界展望會
  • Yahoo 奇摩公益
  • igiving 公益網
  • 兒福聯盟

Copyright © 2021 · Office Guide