12

より大きなプロジェクトの一部である C ソース/ヘッダー ファイルがあります。実際のプロジェクトとは別に、これをユニットとしてテストしたいと思います。C で別の .xml を使用して新しいプロジェクトを作成することでこれを行うことは可能ですがmain()、Python (3) とそのフレームワーク (たとえば、nose) を使用してテストの構築を加速し、既存のレポートを使用できるかどうかを確認したいと思います。フレームワークなど

CFFIでこれができるという印象を受けました。サンプル C ファイルは次のとおりです。

// magic.c
// Implementation of magic.
int add(int a, int b)
{
    return a;
}

ヘッダー:

// magic.h
// Add two numbers (where a + b is not greater than INT_MAX).
int add(int a, int b);

これは、いくつかの関数を呼び出すことができるようにコンパイルしようとするスクリプトです。

# cffi_test.py
import cffi

INCLUDE_DIRS = ('.',)

SOURCES = ('magic.c',)

ffi = cffi.FFI()

ffi.set_source(
    '_magic_tests',
    '#include "magic.h"',
    include_dirs = INCLUDE_DIRS,
    sources = SOURCES,
    libraries = [],
    )

ffi.compile()

最終的には、一連の単体テストの前に、これをセットアップの一部にする予定です。純粋な Python 関数は、テスト セットアップで構築されたオブジェクトを介してtest_add()C 関数の結果を呼び出してチェックします。add()ffi

上記のスクリプトは機能しているようです。エラーなしで実行され、_magic_tests.cファイル、_magic_tests.cp35-win32.pydファイル、およびReleaseディレクトリが作成されます。私もimport _magic_testsエラーなしでできます。

しかし、CFFI 経由で C 関数を実際に呼び出す方法がわかりません。関数のドキュメントが見つかりませんset_source()。プロセス全体にかなり不可欠なようです。概要では多くのことが言及されていますが、参照はそれがまったく含まれていません。ドキュメントには関数の呼び出しに関するセクションがありますが、作成方法を示さずにオブジェクトを参照しています。前の例を見ると、から作成されたオブジェクトがありますが、それを CFFI 自体が生成しているものに適用する方法がわかりません。liblibffi.dlopen()

私の大きな質問 (つまり、私のX 問題) は次のとおりです。

  • CFFI は、クロス プラットフォーム (Windows 7-10、Linux、OS X) の方法で C 関数を呼び出してテストするために使用する合理的なツールですか?

私の現在のアプローチから生じる質問 (つまり、私のY 問題) は次のとおりです。

  • のドキュメントはどこにありますset_source()か? どのような引数が必要かを知るにはどうすればよいですか?
  • lib呼び出したい関数を含むオブジェクトを作成するにはどうすればよいですか?
  • これは、CFFI を使用して C 関数を呼び出す最も簡単な方法ですか? 共有ライブラリや再配布可能パッケージを作成する必要は特にありません。発生する必要がある場合は問題ありませんが、必須ではありません。他にどのようなアプローチを試すことができますか?

私の現在の設定は次のとおりです。

Christoph Gohlke のリポジトリから CFFI と pycparser を使用しています。

4

1 に答える 1

14

私のプロジェクトではcffi、C コードのテストに使用しています。IMHOcffiは、C コードの Python バインディングを生成するための優れたツールであるため、Python から C 関数を呼び出してテストするために使用する合理的なツールであると考えています。ただし、プラットフォームごとにバインディングをコンパイルする必要があるため、コードは C コードと同じようにクロス プラットフォームになります。

以下に、質問に答えるドキュメントへの参照をいくつか示します。さらに、 をどのように使用するかを説明するために、いくつかのサンプル コードを書きcffiました。より大きな例については、 https://github.com/ntruessel/qcgc/tree/master/testで私のプロジェクトを見つけることができます。

あなたの例の4つは、次のbuild_magic_tests.pyようになります。

from cffi import FFI

ffibuilder = FFI()

# For every function that you want to have a python binding,
# specify its declaration here
ffibuilder.cdef("""
    int add(int a, int b);
                """)

# Here go the sources, most likely only includes and additional functions if necessary
ffibuilder.set_source("magic_tests",
    """
    #include "magic.h"
    """, sources=["magic.c"])

if __name__ == "__main__":
    ffibuilder.compile()

magic_tests モジュールを生成するには、python build_magic_tests.py. 生成されたモジュールは、次のようにインポートして使用できます。

from magic_tests import ffi, lib

def run_add():
    assert 4 == lib.add(4, 5)
于 2016-06-21T08:22:36.423 に答える