したいこと
C++で作成した、配列を返すDLLをUnity(C#)で受け取る方法を考察します。
前提
開発環境:Unity 2017 + Visual Studio Community 2017
言語:Unity C#, C++
使用するDLL
C++で以下のコードで生成されたDLLを使用します。
C++の配列の使い方が間違っている気がする汚いコードです。
DllForDebug.cpp
#include "stdafx.h"
#include "DLLForDebug.h"
#include "iostream"
// グローバル変数
int* arr = new int[5];
float* arr_float = new float[5];
char* arr_char = new char[5];
// {0, 1, 2, 3, 4}のint型配列を返す
int* ReturnIntArray()
{
int i = 0;
for (i = 0; i <= 4; i++)
{
arr[i] = i;
}
return arr;
}
// {0, 0.75, 1.50, 2.25, 3}のfloat型配列を返す
float* ReturnFloatArray()
{
int i = 0;
for (i = 0; i <= 4; i++)
{
arr_float[i] = i * 0.75;
}
return arr_float;
}
// {a,i,u,e,o}のchar型配列を返す
char* ReturnCharArray()
{
arr_char[0] = 'a';
arr_char[1] = 'i';
arr_char[2] = 'u';
arr_char[3] = 'e';
arr_char[4] = 'o';
return arr_char;
}
DllForDebug.h
extern "C"
{
__declspec(dllexport) int* ReturnIntArray();
__declspec(dllexport) float* ReturnFloatArray();
__declspec(dllexport) char* ReturnCharArray();
}
Unity上での動作
以下のソースファイルを使用して、Unity上での実行を確認しました。
ここで使用する「Marchal.Copy」についての詳細は、MSDNを参照してください。
RunDLL.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// IntPtr型を使用するのに必要
using System;
// Dllの読み込みに必要
using System.Runtime.InteropServices;
public class RunDLL : MonoBehaviour
{
// Dll内の関数を宣言
[DllImport("DllForDebug")]
private extern static IntPtr ReturnIntArray();
[DllImport("DllForDebug")]
private extern static IntPtr ReturnFloatArray();
[DllImport("DllForDebug")]
private extern static IntPtr ReturnCharArray();
// Use this for initialization
void Start()
{
int i = 0;
// 格納したい配列先
int[] arrInt = new int[5];
float[] arrFloat = new float[5];
char[] arrChar = new char[5];
// 配列の先頭ポインタをIntPtr型の変数にそれぞれ格納する
IntPtr ptrInt = ReturnIntArray();
IntPtr ptrFloat = ReturnFloatArray();
IntPtr ptrChar = ReturnCharArray();
// コピー
Marshal.Copy(ptrInt, arrInt, 0, 5);
Marshal.Copy(ptrFloat, arrFloat, 0, 5);
Marshal.Copy(ptrChar, arrChar, 0, 5);
// Log
for (i = 0;i <=4; i++)
{
Debug.Log(arrInt[i]);
Debug.Log(arrFloat[i]);
Debug.Log(arrChar[i]);
}
}
// Update is called once per frame
void Update()
{
}
}
#結果と問題
Consoleを確認すると、int型とfloat型は正確な情報を手に入れることが確認できます。
何故かchar型が上手くいかない問題…