本日は Python の技術調査枠です。
Python の ctypes で DLL の関数から様々な戻り値を受け取る方法について記事にします。
今回は参照渡しを利用して、値を受け取ってみます。
前回記事の続きです。
bluebirdofoz.hatenablog.com
参照渡しを利用する
関数で参照渡しを利用して、Python スクリプトに値を受け取る例を試してみます。
最初に int 型の参照を受け取って値を代入する関数を用意します。
前回のプロジェクトを修正し、DLL に int* 型を受け取る関数を追加します。
・TestLib.h
#pragma once #ifdef TESTLIB_EXPORTS #define TESTLIB_API extern "C" __declspec(dllexport) #else #define TESTLIB_API extern "C" __declspec(dllimport) #endif TESTLIB_API void ReturnInt(int*);
・TestLib.cpp
void ReturnInt(int* pointer_int) { *pointer_int = 11; }
次に関数を呼び出す Python スクリプトを修正します。
変数の参照を渡す場合は byref() を利用します。
・dllAccesstest04.py
# ctypesインポート from ctypes import * # DLLをロードする dll = cdll.LoadLibrary("TestLib.dll") # 文字列受け取り用の int 型を作成する ret_int = c_int() # 参照を引数に渡して実行する dll.ReturnInt(byref(ret_int)) # 収納された値を表示する print("ReturnInt Execute") print(ret_int) print(ret_int.value)
実行すると、ret_int の値に 11 が設定されたことが確認できました。
文字列を受け取る
次は参照渡しを利用して文字列を返す関数を作成してみます。
文字列を返却する場合、文字列を受け取るバイト列先頭の参照を関数に引き渡す必要があります。
前回のプロジェクトを修正し、DLL に char* 型を受け取る関数を追加します。
・TestLib.h
#pragma once #ifdef TESTLIB_EXPORTS #define TESTLIB_API extern "C" __declspec(dllexport) #else #define TESTLIB_API extern "C" __declspec(dllimport) #endif TESTLIB_API void ReturnString(char*, int);
・TestLib.cpp
#include "stdafx.h" #include "string.h" // strcpy #include "TestLib.h" void ReturnString(char* return_pchar, int length_int) { strcpy_s(return_pchar, length_int, "resultStr"); return; }
次に関数を呼び出す Python スクリプトを修正します。
文字列を収納するバッファは create_string_buffer を使って作成します。
・dllAccesstest04.py
# ctypesインポート from ctypes import * # DLLをロードする dll = cdll.LoadLibrary("TestLib.dll") # 文字列受け取り用のバッファを作成する buffer_length = 10 uni_buffer = create_string_buffer(buffer_length) # バッファを引数に渡して実行する dll.ReturnString(uni_buffer, buffer_length) # 収納された値を表示する print("ReturnString Execute") print(type(uni_buffer)) print(uni_buffer.value)
実行すると、戻り値の"resultStr"の文字列が確認できました。