ホームページ >バックエンド開発 >Python チュートリアル >Python が C/C++ ダイナミック リンク ライブラリを呼び出す方法の詳細な説明

Python が C/C++ ダイナミック リンク ライブラリを呼び出す方法の詳細な説明

WBOY
WBOYオリジナル
2016-06-16 08:43:071797ブラウズ

この記事では、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 ライブラリの機能はまだ調査されていません

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。