[解決済み】C言語のライブラリをPythonでラッピングする。C、Cython、またはctypes?
質問
PythonアプリケーションからC言語のライブラリを呼び出したいのですが、どうすればいいですか?API全体をラップするのではなく、私のケースに関連する関数とデータ型だけをラップしたいのです。私が思うに、私には3つの選択肢があります。
- C言語で実際の拡張モジュールを作成します。おそらくやりすぎで、拡張モジュールの書き方を学ぶためのオーバーヘッドも避けたいところです。
- 使用方法 Cython C ライブラリから Python に関連する部分を公開するためです。
-
全部をPythonで行うには、次のようにします。
ctypes
を使用して外部ライブラリと通信します。
2)と3)のどちらが良いのか迷うところです。3)の利点は
ctypes
は標準ライブラリの一部であり、結果として得られるコードは純粋なPythonになります - ただし、この利点が実際にどの程度大きいかはわかりません。
どちらを選んでもメリット/デメリットがあるのでしょうか?どちらの方法をお勧めしますか?
編集する 回答ありがとうございました。もちろん、1つのケースに対しての判断はまだ必要で、「これが正しい」という答えはありません。私自身の場合は、おそらくctypesを使うことになると思いますが、他のプロジェクトでCythonを試してみるのも楽しみです。
FogleBirdの回答は、ctypesに関する良い洞察を提供しており、また現在最も投票数の多い回答であるため、私はFogleBirdの回答を選択しました。しかし、私は良い概要を得るためにすべての回答を読むことをお勧めします。
本当にありがとうございました。
解決方法は?
ctypes
は早く終わらせるための最善の策であり、まだPythonを書き続けているあなたにとって、楽しく作業できるものです
私は最近 エフティーディーアイ ドライバは、ctypeを使用してUSBチップと通信するためのもので、素晴らしいものでした。 1日足らずですべて完成し、動作するようになりました。(必要な機能だけ、15個ほど実装しました)。
以前はサードパーティのモジュールを使っていました。 PyUSB を、同じ目的で使用することができます。 PyUSBは実際のC/Pythonの拡張モジュールです。 しかし、PyUSBはブロッキングリード/ライトを行うときにGILを解放しないので、私たちに問題を引き起こしていました。 そこで、私はctypesを使用して独自のモジュールを書きました。
注意点としては、types は
#define
の定数などは、使用するライブラリの関数だけなので、自分のコードでそれらの定数を再定義する必要があります。
以下は、最終的にどのようなコードになるかの例です(たくさんの部分を切り取って、要点を示したいだけです)。
from ctypes import *
d2xx = WinDLL('ftd2xx')
OK = 0
INVALID_HANDLE = 1
DEVICE_NOT_FOUND = 2
DEVICE_NOT_OPENED = 3
...
def openEx(serial):
serial = create_string_buffer(serial)
handle = c_int()
if d2xx.FT_OpenEx(serial, OPEN_BY_SERIAL_NUMBER, byref(handle)) == OK:
return Handle(handle.value)
raise D2XXException
class Handle(object):
def __init__(self, handle):
self.handle = handle
...
def read(self, bytes):
buffer = create_string_buffer(bytes)
count = c_int()
if d2xx.FT_Read(self.handle, buffer, bytes, byref(count)) == OK:
return buffer.raw[:count.value]
raise D2XXException
def write(self, data):
buffer = create_string_buffer(data)
count = c_int()
bytes = len(data)
if d2xx.FT_Write(self.handle, buffer, bytes, byref(count)) == OK:
return count.value
raise D2XXException
誰かがやった いくつかのベンチマーク 様々なオプションについて。
C++のライブラリをたくさんのクラス/テンプレート/その他で包まなければならない場合は、もっと躊躇するかもしれません。 しかし、ctypesは構造体をうまく扱うことができ、さらに コールバック をPythonに取り込むことができます。
関連
-
[解決済み】TypeErrorの修正方法。Unicodeオブジェクトは、ハッシュ化する前にエンコードする必要がある?
-
[解決済み】Python - "ValueError: not enough values to unpack (expected 2, got 1)" の修正方法 [閉店].
-
[解決済み] Pythonには文字列の'contains'サブストリングメソッドがありますか?
-
[解決済み] Pythonで現在時刻を取得する方法
-
[解決済み] Pythonで2つのリストを連結する方法は?
-
[解決済み] ファイルのコピー方法について教えてください。
-
[解決済み] Pythonで例外を手動で発生(スロー)させる
-
[解決済み] Python 3で「1000000000000000 in range(1000000000000001)」はなぜ速いのですか?
-
[解決済み】ネストされたディレクトリを安全に作成するには?
-
[解決済み】Pythonに三項条件演算子はありますか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
Pythonを使って簡単なzipファイルの解凍パスワードを手作業で解く
-
Python interpreted model libraryによる機械学習モデル出力の可視化 Shap
-
パッケージングツールPyinstallerの使用と落とし穴の回避
-
[解決済み】終了コード -1073741515 (0xC0000135)でプロセス終了)
-
[解決済み】Python Error: "ValueError: need more than 1 value to unpack" (バリューエラー:解凍に1つ以上の値が必要です
-
[解決済み】Flask ImportError: Flask という名前のモジュールがない
-
[解決済み】NameError: 名前 'self' が定義されていません。
-
[解決済み】 TypeError: += でサポートされていないオペランド型: 'int' および 'list' です。
-
[解決済み】django インポートエラー - core.managementという名前のモジュールがない
-
[解決済み] Pythonによるピッチ検出