(コード付き) はじめに | Python を使用して C/C++ コードを呼び出す方法

編集者のおすすめ

前回の記事では、C/C++ を使用して Python スクリプトを呼び出す方法を紹介しましたが、この記事では、開発におけるもう 1 つの一般的な問題について説明します。Python を使用して開発を行う場合、アルゴリズムによっては計算量が多く実行時間が長くなる場合がありますが、このようなアルゴリズムを C/C++ 言語で実装することでプログラムの実行時間を短縮できます。

Python を使用するのは非常に便利ですが、C/C++ ほど効率的ではありません。さらに、一部の重要なコードを保護したい場合は、これらのコードを C/C++ 動的ライブラリにコンパイルしてから、Python を使用して can を呼び出すことができます。この目標をうまく達成します。

一般に、一般的に使用される実装方法は 2 つあります:
Python 拡張機能を使用して C/C++ コードを作成し、インポートを使用してダイナミック ライブラリを呼び出す Python の ctypes モジュールを使用して
C/C++ ダイナミック ライブラリを直接ロードします (一般的な C/C++ コードを使用します)書き方)。

これらはすべて動的ライブラリとしてコンパイルされていますが、大きなギャップは C/C++ コードの記述にあります。

さまざまな実装方法の違い

1 つ目の方法は、C/C++ 言語に限定されず、他の言語を統合するための Python の拡張メカニズムですが、個人的には 2 つ目の方法の方が理解しやすく実装しやすいと感じています (通常、既存の C/C++ コードを変更する必要はありません)書き換え、またはほんの少しの書き換えのみ)ということで、今日はこのように具体的な実装プロセスを紹介します。

最初のメソッドの実装については、https://docs.python.org/zh-cn/3/c-api/intro.html を参照してください。

この時点で、多くの学生は Cython だ、そうだ、Cython は Python / ctypes の一連の問題 (速度のボトルネックなど) を解決してくれるだろう、と言うかもしれませんが、いくつかの単純なことを始めようとすると、学習コストが高すぎるのは受け入れられないかもしれません。特に C/C++ と Python の経験を持つプログラマーにとっては、単純なことを実行し、高速に実行するのが得意です。Cython と ctypes の選択については、こちらを参照してください: https://www.codenong.com/1942298/

図書館を簡単に紹介します

ライブラリの本質はパッケージ化されたコード パッケージであり、通常、静的ライブラリ (.lib .a) と動的ライブラリ (.dll .so) に分けることができます。前者は一般に Windows 環境のサフィックスであり、後者はLinux 環境のサフィックス。静的ライブラリはメイン プログラムのコンパイル時に最終的な実行可能ファイルにコンパイルされますが、動的ライブラリは呼び出し時に関連するコンテンツを検索します。ctypes には静的ライブラリを呼び出す方法がないため、今回は C/C++ を動的ライブラリにコンパイルします。

基本的な使い方

個人的には、ctypes を使用する利点は、便利であることと、少しの変更で大幅なパフォーマンスの向上につながることがあり、効率とパフォーマンスのバランスを考慮すると最適な選択であると感じています。呼び出しプロセスは通常 2 つのステップに分かれています:
1. C/C++ コードをダイナミック ライブラリにコンパイルする;
2. Python を使用して対応するダイナミック ライブラリを呼び出す。

C/C++ コードを動的ライブラリにコンパイルする

CMake を忘れずに変更してください:

add_library(c_library SHARED src/c_library.cpp)

ここでの SHARED はダイナミック リンク ライブラリを意味します。

ctypes は、使用しているライブラリ内の #define 定数などについては認識せず、関数のみを認識するため、独自のコードでこれらの定数を再定義する必要があります。

単純な合計コードは次のようになります (名前: c_library.cpp)。

#include <stdio.h>

extern "C"
{
    
    
    int add_int(int num1, int num2)
{
    
    
        return num1 + num2;
    }

    float add_float(float num1, float num2)
{
    
    
        return num1 + num2;
    }
}

C++ 関数を呼び出すときは、関数宣言にプレフィックス extern "C" を追加する必要があることに特に注意してください。これは、C++ が関数のオーバーロード関数をサポートしており、コンパイル中に関数名が変更されるためです。したがって、関数が宣言されるとき、コードが C の方法でコンパイルされるように、デフォルトで接頭辞 extern "C" を追加します。

これをコンパイルすると、生成された動的ライブラリが次の図に示されます。

ここに画像の説明を挿入

Python を使用して動的ライブラリを呼び出す

Python がダイナミック リンク ライブラリを呼び出すプロセスは、一般的に次のステップに分かれています:
1. ダイナミック リンク ライブラリをロードする;
2. 入力を C 互換のデータ型に変換する;
3. 出力を C 互換のデータ型に変換する;
4. . ダイナミック ライブラリ関数を呼び出します。

完全なコードは次のようになります。

import ctypes
import os
import sys

#Load the shared object file
if sys.platform == "win32":
    c_library = ctypes.CDLL(os.path.abspath(
        '.')+"/out/build/x64-Debug/c_cxx/c_library/libc_library.dll")
    print
elif sys.platform == "linux":
    c_library = ctypes.CDLL(os.path.abspath(
        '.')+"/build/c_cxx/c_library/libc_library.so")

#Find sum of integers
res_int = c_library.add_int(4, 5)
print("Sum is : " + str(res_int))

#Find sum of floats
a = ctypes.c_float(5.5)  # 输入转换为C兼容的数据类型
b = ctypes.c_float(4.1)

c_library.add_float.restype = ctypes.c_float  # 输出转换为C兼容的数据类型

print("Sum is : ", str(c_library.add_float(a, b)))

確か、int型は変換する必要がなかったので、コードは書きませんでした。

Python コードを実行すると、結果は次のようになります。

ここに画像の説明を挿入
ctypes 関連の操作の詳細については、https://docs.python.org/3/library/ctypes.html を参照してください。

ctypes でよく使用される変数の型と C の型の対応表:

ここに画像の説明を挿入

参考文献

1.https://zhuanlan.zhihu.com/p/36772947
2.https://blog.csdn.net/u012247418/article/details/80170690

おすすめ

転載: blog.csdn.net/weixin_41006390/article/details/126459715
おすすめ