こんにちは、Unityエンジニアのオオバです。
C#とC++間のデータやりとりを
実装したことありますか?
Unityが提供する機能を普通に使っているだけだと、
あまり出てこないシチュエーションかも知れません。
Unityが提供していない機能にアクセス といった
Unityの外へ一歩出ようとすると
C++や別の言語が必要になります。
今回はC#とC++間のデータのやり取りの第一歩として、
C#からC++へ文字列の送信を解説します。
C#からC++に文字列を渡す4つのポイント
- ① : C++は char型のポインタ で受け取る
- ② : C++のメソッドに
extern "C"
をつける - ③ : C#側は
DllImport
属性をつける - ④ : C#側に
static extern
を付与
やり方が分かれば意外と簡単です。
ざっくりした手順はコチラ
- C++からのTestDll.dllを生成
- TestDll.dllをC#から呼び出す
C#側から文字列を引き渡して、
C++側でログを出力してみます。
環境構築を含めて詳細を解説していきます。
👉DOTweenの教科書を読んでUnityアニメーションをプログラミングしてみよう!
【環境構築】 DLLプロジェクトを作成
Visual Studio Community 2017で開発を進めていきます。
新しいプロジェクトを作成し、
ダイナミックリンクライブラリ(DLL) を選びます。
プロジェクトを作ると
デフォルトでファイルが
いくつか作られますが気にせず進めます。
C#側に公開するC++の関数アトリビュートの定義
まずはC#からC++を呼ぶための準備です。
extern "C"{
// C#から呼ばれたい関数を定義
}
C#から呼ばれる関数に↑の記述が必要になります。
今回はマクロを使って開発効率を上げます。
#define DllExport extern "C" __declspec(dllexport)
↑の1行をstdafx.h
に追加してマクロを作成。
// hoge()をC#から呼べるようになる
DllExport void hoge();
↑このようにDllExport
属性を
関数定義の先頭に記述することで
C#から呼べるように します。
さきほど登場したstdafx.h
は、
プロジェクト作成時に作られるヘッダファイルです。
このファイルの行末あたりに1行追加しておきます。
💻ソースコード : stdafx.h
#pragma once
#include "targetver.h"
// Windows ヘッダーからほとんど使用されていない部分を除外する
#define WIN32_LEAN_AND_MEAN
// Windows ヘッダー ファイル
#include <windows.h>
// プログラムに必要な追加ヘッダーをここで参照してください
#define DllExport extern "C" __declspec(dllexport)
なぜextern 'C'をつけるのか?
そもそもなぜC#からC++を呼ぶ際に、
extern "C"
が必要のか?疑問ですよね。
理由はC++のコンパイルにあります。
C++はコンパイルのたびにメソッド名が変わります。
extern "C"
を記述することで、 メソッド名を固定 します、
つまりC#側から呼び出したときのリンクエラーを防ぐために必要なのです。
準備が完了したため、
C#からC++に文字列を送る実装を進めます。
C++側はcharのポインタで受け取る
最初に悲報ですが、
C#からC++にstring型をそのまま送れません。
C++側はC#の文字列を
ポインタで受け取ります。
#include "stdafx.h"
#include <iostream>
// C#から呼ばれる関数の定義
DllExport void Test(const char* str);
void Test(const char* str)
{
if (str == NULL) {
std::cout << "str is null." << std::endl;
return;
}
std::cout << str << std::endl;
}
C++側はString型ではなく、
char型のポインタで定義します。
DllExport属性をTestメソッドにくっつけることで、
C#側から実行できるようになります。
C++のDLL化
C++の処理をC#から呼び出すために
dllファイルに固めます。
C++側の実装が完了したのでビルドします。
- プロジェクトを右クリック
- ビルド
すると TestDll.dll
が出来上がります。
このDLLをC#プロジェクトのexeと同階層に配置します。
C#側でDLLをインポートしてC++のメソッドを呼ぶ
C#の実装に移ります。
まずはソースから見ていきましょう。
[DllImport("TestDll.dll", CallingConvention = CallingConvention.Cdecl)]
static extern void Test(string str);
static void Main()
{
Test("hogehoge");
}
ポイントは3点
- C++で定義した関数と同名の関数を定義
static extern
を付与[DllImport("DLLファイル名", CallingConvention = CallingConvention.Cdecl)]
属性付与
詳しいことはいったん置いておきます。
この状態でC#を実行してみます。
するとコンソールにhogehogeと出力されるでしょう。
まとめ : C#からC++(DLL)に文字列を渡す
C#からC++に文字列を送信する手順を紹介してきました。
- C++はchar型のポインタで受け取る
- C#側にC++のメソッドを公開するために
extern "C"
が必要 - C#側は
DllImport
属性が必要 - C#側にC++で定義したメソッドに
static extern
を付与して定義
以上のポイントを抑えておきましょう。
C#/C++間データやり取りの基礎となる情報です。
C++はchar型のポインタで受け取るという点以外は、
C#側からはString型をそのまま送れるため、
実装自体はシンプルだったのではないかと思います。
C#からC++にintを渡す方法
引き続きさまざまなデータの型をC#/C++間で
やり取りしていきます。
お楽しみに!
この記事が気に入ったらフォローしよう
- VisualStudioCommunity2017 v15.9.8
- Windows10