備忘録

備忘録

C++(EXE)からC#(DLL)の関数を呼び出す

Ⅰ. はじめに

C++(EXE)からC#(DLL)の関数を呼び出す」方法です。
いくつか方法があり、それぞれにメリットデメリットがあります。

# 概要 メリット デメリット
1 C++/CLIを使う ・一番簡単。
・VisualStudioのIntelliSenseも使える。
・プロジェクトの設定で「CLIを使う」に変更する必要がある。
2 C#(DLL)側で関数をエクスポートする ・「CLIを使う」設定に変更しなくて良い。
・GetProcAddressが使える為、よく知られた方法で関数を呼び出す事ができる。
C#(DLL)側のソースコードが無い場合利用できない。
3 C#(DLL)側をCOM 参照可能にする ・「CLIを使う」設定に変更しなくて良い。 C++側のコード量が無駄に増える。めんどくさい。
4 C#(DLL)に対するC++/CLIのラッパープロジェクトを作り、C++プロジェクトから使う ・「CLIを使う」設定に変更しなくて良い。
・「COMは使いたくない」かつ「元のプロジェクトの設定をどうしても変更したくない場合」に使える。
・やり方がスマートではない。

C++/CLIを使う事がデメリットにならないケースもあります

1, 2をこの記事で紹介します。
3についてはこちら
4についてはこちら

逆の「C#(EXE)からC++(DLL)の関数を呼び出す」場合はこちら
http://kagasu.hatenablog.com/entry/2017/03/27/214742

Ⅱ. 「C++/CLIを使う」方法

1. C++のプロジェクト設定を開き「共通言語ランタイム サポート (/clr)」に変更する
2. サンプルプログラム

Class1.cs

namespace DllExportTest
{
  public class Class1
  {
    public static int Sum(int a, int b)
    {
      return a + b;
    }
  }
}

MyApp.cpp

#include <Windows.h>
#include <iostream>

#using "DllExportTest.dll"

using namespace DllExportTest;

int main()
{
  std::cout << Class1::Sum(1, 2) << std::endl;
  return 0;
}
3. 実行結果
$ MyApp.exe
3

Ⅲ. 「C#(DLL)側で関数をエクスポートする」方法

動画はこちら

1. サンプルプログラム

Class1.cs

using System;
// Install-Package Conari
using net.r_eg.Conari.Types;

namespace DllExportTest
{
  public class Class1
  {
    [DllExport]
    public static int Sum(int a, int b)
    {
      return a + b;
    }

    [DllExport]
    public static IntPtr SayHello(string name)
    {
      var str = $"Hello {name}";
      var unmanagedStr = new UnmanagedString(str, UnmanagedString.SType.Ansi);
      return unmanagedStr;
    }
  }
}

MyApp.cpp

#include <Windows.h>
#include <iostream>

typedef int (*Sum)(int a, int b);
typedef char* (*SayHello)(const char* name);

int main()
{
  auto hModule = LoadLibrary(L"DllExportTest.dll");
  auto sum = reinterpret_cast<Sum>(GetProcAddress(hModule, "Sum"));
  std::cout << sum(1, 2) << std::endl;

  auto sayHello = reinterpret_cast<SayHello>(GetProcAddress(hModule, "SayHello"));
  std::cout << sayHello("tanaka") << std::endl;
  return 0;
}
2. DllExport.bat をダウンロードする

https://github.com/3F/DllExport/releases

3. DllExport.bat を .sln と同じ階層にコピーする
4. コマンドプロンプトを開いて以下を実行する
DllExport.bat -action Configure
5. Installedにチェックを入れ、Applyをクリックする

f:id:kagasu:20171231215101p:plain

6. VisualStudioでプロジェクトを再ビルドする
7. 関数がエクスポートされる

f:id:kagasu:20171231215416p:plain

8. 実行結果
$ MyApp.exe
3
Hello tanaka