[Python][FFI] ctypes で C++ メソッドから文字列を受け取る

  • 2022年8月20日
  • 2022年9月17日
  • Python
  • 115View
  • 0件

はじめに

Python 標準ライブラリ ctypes を利用して、C++ メソッドから文字列を受け取ります。

動作環境は以下です。

  • Windows 11
  • WSL Ubuntu (20.04)
  • g++ 9.4.0
  • Python 3.8.10

サンプルコード

C++ ライブラリ

C++ 側の print メソッドでは、固定の文字列を返却します。

extern "C" const char *get_str()
{
    return "Hello!";
}
$ g++ --shared -fPIC getstr.cc -o libgetstr.so

Python スクリプト

Python 側では、C++ から受け取った文字列を標準出力に出力します。

import ctypes
import pathlib

dirname = pathlib.Path(__file__).parent.resolve()
libpath = dirname.joinpath("libgetstr.so")
lib = ctypes.cdll.LoadLibrary(libpath)

lib.get_str.restype = ctypes.c_char_p
print(lib.get_str().decode())
$ python3 main.py
Hello!

サンプルコード(ワイド型文字列)

C++ 側からワイド型の文字列を返却するケースのサンプルも掲載します。

C++ ライブラリ

戻り値の型を wchar_t とし、文字列にプリフィックス L を付与します。
これでワイド型の文字列が返却されます。

extern "C" const wchar_t *get_str()
{
    return L"Hello!";
}
$ g++ --shared -fPIC getstr.cc -o libgetstr.so

Python スクリプト

Python 側では、以下2点の修正を加えます。

  • restypec_char_p から c_wchar_p に変更する。
  • 文字列に対する .decodo() を除去する。
import ctypes
import pathlib

dirname = pathlib.Path(__file__).parent.resolve()
libpath = dirname.joinpath("libgetstr.so")
lib = ctypes.cdll.LoadLibrary(libpath)

lib.get_str.restype = ctypes.c_wchar_p
print(lib.get_str())
$ python3 main.py
Hello!