ctypes-初心者


100

私は、PythonライブラリにCライブラリを「ラッピング」するタスクを持っています。この件に関して、ドキュメントは非常にあいまいです。彼らは、上級のpythonユーザーだけがctypesを実装することを期待しているようです。まあ私はpythonの初心者であり、助けが必要です。

一歩一歩手助けが素晴らしいでしょう。

だから私は私のcライブラリを持っています。私は何をしますか?どのファイルをどこに置きますか?ライブラリをインポートするにはどうすればよいですか?Pythonに「自動ラップ」する方法があるかもしれないと読んだことがありますか?

(ちなみに、私はpython.netでctypesチュートリアルを実行しましたが、機能しません。つまり、残りの手順を実行できるはずだと彼らが思っているのです。

実際、これは私が彼らのコードで得るエラーです:

File "importtest.py", line 1
   >>> from ctypes import *
   SyntaxError: invalid syntax

私は本当にこれについていくつかの段階的なヘルプを使うことができました!ありがとう〜


10
あなたは持っています>>> importtest.pyに?人々が>>> 各行にあるコードを投稿するとき、それはインタラクティブシェルで実行されていることを示しています。ファイルから実行するには、>>> 出現する場所(3>記号とスペース)を削除します。
Chinmay Kanchi

4
>>>sを入力しないでください。これらは対話型シェルによって出力され、ソースファイルから除外する必要があります。
nmichaels

8
>>>.pyファイルで!痛い!これまで見たことがない!
デビッドヘ

3
正直なところ、ctypesをいじる前に、Pythonを少し(少なくとも少し)学んでください。基本的なPythonを知らないことを前提としたctypesのチュートリアルを見つけることは決してありません。
Chinmay Kanchi、

3
@spentak:助けを求める場合は、適切な情報を提供してください。少なくとも、あなたが話しているコードの最新バージョンを見せてください。たとえば、「行3」には何がありますか?
フランチェスコ

回答:


228

これは、素早くて汚いctypesチュートリアルです。

まず、Cライブラリを記述します。次に、簡単なHello worldの例を示します。

testlib.c

#include <stdio.h>

void myprint(void);

void myprint()
{
    printf("hello world\n");
}

共有ライブラリとしてコンパイルします(ここでMacの修正を見つけます):

$ gcc -shared -Wl,-soname,testlib -o testlib.so -fPIC testlib.c

# or... for Mac OS X 
$ gcc -shared -Wl,-install_name,testlib.so -o testlib.so -fPIC testlib.c

次に、ctypesを使用してラッパーを記述します。

testlibwrapper.py

import ctypes

testlib = ctypes.CDLL('/full/path/to/testlib.so')
testlib.myprint()

それを実行します:

$ python testlibwrapper.py

そして、あなたは出力を見るはずです

Hello world
$

すでにライブラリを念頭に置いている場合は、チュートリアルのPython以外の部分をスキップできます。ctypesがライブラリ/usr/libまたは別の標準ディレクトリにライブラリを配置できることを確認してください。これを行う場合、ラッパーを作成するときに完全なパスを指定する必要はありません。これを行わない場合は、を呼び出すときにライブラリの完全パスを指定する必要ありますctypes.CDLL()

これはより包括的なチュートリアルの場所ではありませんが、このサイトで特定の問題についてヘルプを求める場合、コミュニティがあなたを助けると確信しています。

PS:Linuxを使用していると思いますctypes.CDLL('libc.so.6')。別のOSを使用している場合、状況は少し(またはかなり)変化する可能性があります。


1
@ Chinmay:Cの代わりにWindows用の同様のコードを使用できますか?ビジュアルc ++の例を提供していただけませんか?ライブラリを読み込むことはできますが、.dllファイルから関数にアクセスできません。常に「関数 'xyz'が見つかりません」と表示されます。これを回避する方法を教えていただけますか?乾杯。
ネオフィル

私はWindowsの開発についてはあまり知りませんが、Windowsは何かおかしなことをしているようです。おそらく別の呼び出し規約を使用していますか?おそらく、「extern C」を使用してC ++関数のエクスポートを検索する可能性がありますか?
Chinmay Kanchi、2011

はい、私はそれをしましたが、今のところ運がありません。
Neophile

6
ctypeの基本的な機能を示す簡単に実行できるチュートリアルをありがとう
okysabeni

1
クイックアンドダーティーは常に最高のチュートリアルです
lurscher '10

54

Chinmay Kanchiの答えは素晴らしいですが、C ++コードに変数/配列を渡して返す関数の例が必要でした。他の人に役立つので、ここに含めておきます。

整数の受け渡し

整数を受け取り、戻り値に1を加える関数のC ++コード、

extern "C" int add_one(int i)
{
    return i+1;
}

ファイルとして保存されtest.cpp必要な extern "C" に注意してください(これはCコードでは削除できます)。これはg ++を使用してコンパイルされており、Chinmay Kanchiの回答と同様の引数があります。

g++ -shared -o testlib.so -fPIC test.cpp

Pythonコードは、Pythonスクリプトと同じディレクトリにある共有ライブラリへのパスを想定して使用load_librarynumpy.ctypeslibます。

import numpy.ctypeslib as ctl
import ctypes

libname = 'testlib.so'
libdir = './'
lib=ctl.load_library(libname, libdir)

py_add_one = lib.add_one
py_add_one.argtypes = [ctypes.c_int]
value = 5
results = py_add_one(value)
print(results)

これは期待どおり6を印刷します。

配列の受け渡しと印刷

Cコードで配列の要素を出力するには、次のように配列を渡すこともできます。

extern "C" void print_array(double* array, int N)
{
    for (int i=0; i<N; i++) 
        cout << i << " " << array[i] << endl;
}

以前と同じようにコンパイルされ、同じ方法でインポートされます。この関数を使用するための追加のPythonコードは次のようになります。

import numpy as np

py_print_array = lib.print_array
py_print_array.argtypes = [ctl.ndpointer(np.float64, 
                                         flags='aligned, c_contiguous'), 
                           ctypes.c_int]
A = np.array([1.4,2.6,3.0], dtype=np.float64)
py_print_array(A, 3)

ここで、配列を指定します。最初の引数はprint_array、整列されたc_contiguous 64ビットfloatのNumpy配列へのポインターとして、2番目の引数は、Numpy配列の要素数をCコードに伝える整数として指定します。これは、Cコードによって次のように出力されます。

1.4
2.6
3.0

5
これは素晴らしい補足的な回答です。残念ながら、答えを2つにできません:(
jtlz2

明白すぎるかどうかはわかりませんが、コードにエラーがあります。欠品import numpy as npです。そうでなければ、それはnp.float64他のものを見つけることができません。
ベン

@ベン、グッドスポット、追加
エドスミス

11

まず>>>、Pythonの例にあるコードは、それがPythonコードであることを示す方法です。Pythonコードを出力から分離するために使用されます。このような:

>>> 4+5
9

ここで、始まる行が>>>Pythonコードであり、9がその結果であることがわかります。これが、Pythonインタープリターを開始した場合の外観です。そのため、このようになっています。

>>>パーツを.pyファイルに入力することはありません。

これで構文エラーが処理されます。

次に、ctypesはPythonライブラリをラップするいくつかの方法の1つにすぎません。他の方法は SWIGです。これはPythonライブラリを調べ、C APIを公開するPython C拡張モジュールを生成します。もう1つの方法は、Cythonを使用することです。

それらにはすべて利点と欠点があります。

SWIGはC APIのみをPythonに公開します。つまり、オブジェクトも何も取得されず、それを行う別のPythonファイルを作成する必要があります。ただし、「wowza」と呼ばれるモジュールと、C APIのラッパーである「_wowza」と呼ばれるSWIGモジュールを使用することは一般的です。これは、物事を行うのに便利で簡単な方法です。

CythonはC-Extensionファイルを生成します。これには、作成するすべてのPythonコードがCで作成されるという利点があるため、作成するオブジェクトもCで作成されるため、パフォーマンスが向上します。しかし、Cとどのようにインターフェースするかを学ぶ必要があるので、Cの使い方を学ぶのは少し余分な作業です。

ctypesには、コンパイルするCコードがないという利点があるため、他の誰かが作成した標準ライブラリをラップするのに使用すると非常に便利で、WindowsおよびOS Xのバイナリバージョンにはすでに存在します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.