見出し画像

C#からDLL化したC++を実行する方法

1. C#からC++を呼び出したい

 C++でGUIを作成することは、意外と面倒である。そこで、C#でGUIを作成し、C++をDLL化して呼び出せないか検討した。当初は簡単だろうと思ったが、躓くところが多くあったため、手順をまとめる。

2. 動作環境

 動作環境を以下に示す。

 OS: Windows 10
 ツール:Visual Studio 2019 Community Edition

3. 今回の目標

 今回の目標は、C#(Windows Form Application)からC++のDLLを呼び出すことである(図1)。

図1 今回の目標

 C#は、GUIが比較的作成しやすく、安全装置もついているため、初心者にはとっつきやすい。一方、C++は、実行速度は速いが、GUI作成には不向きである。

 そこで、C#でGUIを作成し、具体的な処理はC++をDLL化して呼び出せないか検討した。

4. C++のDLLを作成する

 まず、C++のDLLから作成する。

4.1 新規に空のプロジェクトを作成する

 Visual Studioから、ファイル→新規作成→プロジェクトを選択し、新規プロジェクトを作成する。プロジェクトは、「空のプロジェクト」でよい。

4.2 *.cpp、*.hファイルを追加する

 任意の名前の*.cppと*.hファイルを追加する。プログラムは二つの引数を加算する関数である。

//add.h
#pragma once
#ifndef ADD_HPP
#define ADD_HPP

extern "C"
{
    __declspec(dllexport) int __stdcall add(int a, int b) {
        return a + b;
    }
}
#endif
//add.cpp

#include "add.h"

4.3 作成したC++からDLLを作成する

 C++で作成したプロジェクトからDLLを出力する。図2に示す構成の種類を「ダイナミックライブラリ(.dll)」に変更する。

図2 DLLを生成する設定

 また、DLLを作るときは、プラットフォームが32ビットか64ビットにも注意する。図2のように設定がx86(32ビット)になっているとビルドが通らない。

図3 プラットフォーム構成(32ビットの場合)
図4 プラットフォーム構成(64ビットの場合)

 今回は、図4のようにプラットフォームをx64に設定した。これでプロジェクトをビルドすると、正常にDLLファイルを出力できる。これでC++をDLL化することができた。

5. C#のプロジェクトを作成する

 次は、DLLを呼び出すC#のプロジェクトを作成する。

5.1 新規プロジェクト作成

 Visual Studioから、ソリューションプロジェクトを右クリック→追加→新しいプロジェクトを選択する。プロジェクトの種類は、Windowsフォームアプリケーションとして作成する。

5.2 呼び出し処理の追加

 C#のForm.csにDLLの呼び出し部分を追加する。

using System
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

//以下を追加
using System.Runtime.InteropServices;
//ここまで

namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        //以下を追加
        [DllImport(@"C:\Users\username\source\repos\Project1\WindowsFormsApp1\bin\Debug\Project1.dll", EntryPoint =
        "add", CallingConvention = CallingConvention.StdCall)]
        public static extern int add(int x, int y);
        //ここまで

        public Form1()
        {
            InitializeComponent();
            //以下を追加
            a = add(1,2);
            //ここまで
        }
    }
}

 DllImportのパスをC#の実行ファイルがあるところに設定する。また、そこに作成したDLLを入れておく。その場合、実行時にはDLLを見に行く。

 DLL側でデバッグができるようにDebugモードで実行できるようにする。この設定は、ネイティブコードデバッグにチェックを付ける(図5)。

図5 ネイティブコードデバッグを有効にするチェック 

 筆者は、DLLにするとソースコードは見れないものと思っていたが、設定次第ではDLLの中も見れるようだ。

5.3 どうやら動かない

 DLLを動作したが、図6のエラーが発生した。

図6 予期せぬエラー

 メッセージから、「間違ったフォーマット」と書いてある。おそらく、32ビットと64ビットの構成の違いではないかと察しがついた。

5.4 対象プラットフォームの設定

 設定を調べると、C#の対象プラットフォームが32ビットとなっていることが分かった。初期状態のC#は、対象プラットフォームが32ビットを選ぶにチェックが付いている。この場合、64ビット向けで作成したDLLがエラーとなるようだ。

図7 対象プラットフォームの設定 

 図8のように対象プラットフォームを64ビットに変更する。

図8 対象プラットフォームの設定

6. 実行する

 対象プラットフォームが変更できたので、実行する。C#のプロジェクトをデバッグ実行させる(図9)。

図9 実行結果

 図9に示すようにC#フォームアプリケーションからDLL化したC++を呼び出すことができた。めでたしめでたし。

7. おわりに

 今回は、C#からC++でDLL化したプログラムを呼び出す手順をまとめた。一番苦労したのは、32ビットでビルドするとうまくいかなかったことである。

 プログラミング言語によっては、得意・不得意が存在する。今回は、GUIの作成をC#で行い、具体的な処理をC++で実装できないか検討した。C++をDLL化することで、この問題は解決できそうである。このような使い方をするプログラムを作成する場合には参考にしてほしい。

参考文献

 基本的な手順は以下を参考にした。

https://learn.microsoft.com/ja-jp/visualstudio/debugger/how-to-debug-managed-and-native-code?view=vs-2022

いいなと思ったら応援しよう!