ホームページ >バックエンド開発 >Python チュートリアル >Python が C/C++ ダイナミック リンク ライブラリを呼び出す方法の詳細な説明
この記事では、Python が C/C++ DLL ダイナミック リンク ライブラリを呼び出す方法を例を使用して説明します。具体的な例は次のとおりです。
例 1:
まず、DLL プロジェクトを作成します (この例の作成環境は VS 2005)、ヘッダー ファイル:
//hello.h #ifdef EXPORT_HELLO_DLL #define HELLO_API __declspec(dllexport) #else #define HELLO_API __declspec(dllimport) #endif extern "C" { HELLO_API int IntAdd(int , int); }
CPP ファイル:
//hello.cpp #define EXPORT_HELLO_DLL #include "hello.h" HELLO_API int IntAdd(int a, int b) { return a + b; }
ここで注意すべき点が 2 つあります:
(1) コンパイル時に関数呼び出し規則が __cdecl か __stdcall かを確認します。これは、DLL 内の関数呼び出し規則に従って、Python は対応する関数を使用して DLL をロードするためです。
(2) C++ プロジェクトが使用されている場合、エクスポートされた関数が Python で認識されるように、エクスポートされたインターフェイスには extern "C" が必要です。
私のプロジェクトでは、__cdecl 関数呼び出し規約を使用してコンパイルおよびリンクして hello.dll を生成し、Python の ctypes ライブラリを使用して hello.dll をロードして関数呼び出しを行います。
from ctypes import * dll = cdll.LoadLibrary('hello.dll'); ret = dll.IntAdd(2, 4); print ret;
この時点で、最初の小さなサンプルが完成したので、読者は自分で試してみることができます。
例 2:
この例は単なる「hello world」レベルのプログラムです。実際のアプリケーションでは、ニーズを満たすためにさらに多くのデータ構造、文字列などを渡す必要があります。次に、この例では、データ構造パラメーターを渡す方法と、データ構造を通じて戻り値を取得する方法を示します。
まず、DLL プロジェクトにヘッダー ファイルを書き込みます:
//hello.h #ifdef EXPORT_HELLO_DLL #define HELLO_API __declspec(dllexport) #else #define HELLO_API __declspec(dllimport) #endif #define ARRAY_NUMBER 20 #define STR_LEN 20 struct StructTest { int number; char* pChar; char str[STR_LEN]; int iArray[ARRAY_NUMBER]; }; extern "C" { //HELLO_API int IntAdd(int , int); HELLO_API char* GetStructInfo(struct StructTest* pStruct); }
CPP ファイルは次のとおりです:
//hello.cpp #include <string.h> #define EXPORT_HELLO_DLL #include "hello.h" HELLO_API char* GetStructInfo(struct StructTest* pStruct) { for (int i = 0; i < ARRAY_NUMBER; i++) pStruct->iArray[i] = i; pStruct->pChar = "hello python!"; strcpy (pStruct->str, "hello world!"); pStruct->number = 100; return "just OK"; }
GetStructInfo 関数は、StructTest 型のポインターを渡し、オブジェクト内のプロパティに値を割り当て、最後に「just OK」を返します。
次のように Python 呼び出しコードを記述します。まず、Python で Structure を継承して C DLL と一致するデータ構造 StructTest を構築し、次に関数 GetStructInfo のパラメーターの型と戻り値の型を設定し、最後にStructTest オブジェクトを追加し、パラメーターとしてポインターに変換され、関数 GetStrcutInfo を呼び出し、最後にデータ構造 の値を出力することで呼び出しが成功したかどうかを確認します:
from ctypes import * ARRAY_NUMBER = 20; STR_LEN = 20; #define type INTARRAY20 = c_int * ARRAY_NUMBER; CHARARRAY20 = c_char * STR_LEN; #define struct class StructTest(Structure): _fields_ = [ ("number", c_int), ("pChar", c_char_p), ("str", CHARARRAY20), ("iArray", INTARRAY20) ] #load dll and get the function object dll = cdll.LoadLibrary('hello.dll'); GetStructInfo = dll.GetStructInfo; #set the return type GetStructInfo.restype = c_char_p; #set the argtypes GetStructInfo.argtypes = [POINTER(StructTest)]; objectStruct = StructTest(); #invoke api GetStructInfo retStr = GetStructInfo(byref(objectStruct)); #check result print "number: ", objectStruct.number; print "pChar: ", objectStruct.pChar; print "str: ", objectStruct.str; for i,val in enumerate(objectStruct.iArray): print 'Array[i]: ', val; print retStr;
概要:
1. 64 ビット Python を使用して 32 ビット DLL をロードするとエラーが発生します
2. 上記はほんの一部のテスト プログラムです。Python を作成する際は、可能な限り "try Except" を使用してください。
3. Python が C DLL と対話するときのバイト アライメントの問題に注意してください
4. ctypes ライブラリの機能はまだ調査されていません