MRが楽しい

MRやVRについて学習したことを書き残す

PythonのctypesでDLLの関数から様々な戻り値を受け取る その3(構造体)

本日は Python の技術調査枠です。
Python の ctypes で DLL の関数から様々な戻り値を受け取る方法について記事にします。
f:id:bluebirdofoz:20191119090010j:plain

前回記事の続きです。
bluebirdofoz.hatenablog.com

構造体を受け取る

次に DLL 内で定義した構造体のデータを受け取ってみます。
DLL に以下の通り、構造体を定義します。こちらも参照渡しで構造体型を受け取る関数を追加します。
・TestLib.h

#pragma once

#ifdef TESTLIB_EXPORTS
#define TESTLIB_API extern "C" __declspec(dllexport)
#else
#define TESTLIB_API extern "C" __declspec(dllimport)
#endif

struct vector3 {
    int x;
    int y;
    int z;
};

struct databox {
    int id;
    char name[10];
    vector3 point;
};

TESTLIB_API void ReturnStruct(databox*);

・TestLib.cpp

#include "stdafx.h"
#include "string.h" // memcpy
#include "TestLib.h"

void ReturnStruct(databox* return_databox)
{
    vector3 vecter_result;
    vecter_result.x = 10;
    vecter_result.y = 30;
    vecter_result.z = 60;
    databox databox_result;
    databox_result.id = 3;
    strcpy_s(databox_result.name, 10, "TestData");
    databox_result.point = vecter_result;
    memcpy(return_databox, &databox_result, sizeof(databox));
}

次に関数を呼び出す Python スクリプトを修正します。
構造体のデータ構造を Python スクリプト側で Structure の派生クラスとして定義します。
このとき、クラス内のフィールド型は ctypes 型に含まれる型である必要があります。
構造体の中に構造体を定義することも可能です。

class VECTOR3(Structure):
    _fields_ = [("x", c_int), ("y", c_int), ("z", c_int)]
class DATABOX(Structure):
    _fields_ = [("id", c_int), ("name", c_char * 10), ("point", VECTOR3)]

以下の通り、構造体を受け取って表示するスクリプトを作成しました。
・dllAccesstest05.py

# ctypesインポート
from ctypes import *

# クラスを定義する
class VECTOR3(Structure):
    _fields_ = [("x", c_int), ("y", c_int), ("z", c_int)]
class DATABOX(Structure):
    _fields_ = [("id", c_int), ("name", c_char * 10), ("point", VECTOR3)]

# DLLをロードする
dll = cdll.LoadLibrary("TestLib.dll")
# 構造体を生成する
p_databox = DATABOX()
# 引数に構造体を渡して関数を実行する
dll.ReturnStruct(byref(p_databox))
# 収納された値を表示する
print("ReturnStruct Execute")
print(p_databox.id)
print(p_databox.name)
print(p_databox.point.x)
print(p_databox.point.y)
print(p_databox.point.z)

実行すると、構造体に代入された値が取得できました。
f:id:bluebirdofoz:20191119090023j:plain