「C++の応用 - C Sharp DLLの使用」の版間の差分

提供:MochiuWiki - SUSE, Electronic Circuit, PCB
ナビゲーションに移動 検索に移動
編集の要約なし
95行目: 95行目:


== C++/CLIのラッパープロジェクトを使用する方法 ==
== C++/CLIのラッパープロジェクトを使用する方法 ==
まず、以下に示すソースコードのC# DLLを作成する。<br>
  <syntaxhighlight lang="c#">
  <syntaxhighlight lang="c#">
  // CSharpDLL.cs
  // CSharpDLL.cs
118行目: 119行目:
  </syntaxhighlight>
  </syntaxhighlight>
<br>
<br>
[参照の追加]にて上記のDLLを追加する。<br>
次に、以下に示すようなソースコードのC++/CLI DLLを作成する。<br>
Visual C++のプロジェクト設定を開いて、[構成プロパティ] - [全般] - [共通言語ランタイム サポート (/clr)]に変更する。<br>
その時、ソリューションエクスプローラからC++/CLIプロジェクトを右クリックして[参照の追加]を選択、上記で作成したC# DLLファイルを追加する。<br>
同様に、[構成プロパティ] - [C/C++] - [プリプロセッサ] - [プリプロセッサの定義]項目に、DLLを追加する。<br>
<br>
また、Visual C++のプロジェクト設定を開いて、[構成プロパティ] - [全般] - [共通言語ランタイム サポート (/clr)]に変更する。<br>
同様に、[構成プロパティ] - [C/C++] - [プリプロセッサ] - [プリプロセッサの定義]項目に、<code>DLL</code>プリプロセッサを追加する。<br>
  <syntaxhighlight lang="c++">  
  <syntaxhighlight lang="c++">  
  // CppCLIDLL.cpp
  // CppCLIDLL.cpp
160行目: 163行目:
  </syntaxhighlight>
  </syntaxhighlight>
<br>
<br>
Visual C++のプロジェクト設定を開いて、[構成プロパティ] - [C/C++] - [全般] - [追加のインクルードディレクトリ]項目に、<br>
最後に、以下に示すようなC++のソースコードのプロジェクトを作成する。<br>
その時、メニューバーから[Visual C++のプロジェクト設定]を選択して、[構成プロパティ] - [C/C++] - [全般] - [追加のインクルードディレクトリ]項目に、<br>
CppCLIDLL.hが存在するディレクトリを追加する。<br>
CppCLIDLL.hが存在するディレクトリを追加する。<br>
<br>
同様に、[構成プロパティ] - [リンカー] - [全般] - [追加のライブラリディレクトリ]項目に、CppCLIDLL.libが存在するディレクトリを追加する。<br>
同様に、[構成プロパティ] - [リンカー] - [全般] - [追加のライブラリディレクトリ]項目に、CppCLIDLL.libが存在するディレクトリを追加する。<br>
更に、[構成プロパティ] - [リンカー] - [入力] - [追加の依存ファイル]項目に、CppCLIDLL.libを追加する。<br>
さらに、[構成プロパティ] - [リンカー] - [入力] - [追加の依存ファイル]項目に、CppCLIDLL.libを追加する。<br>
  <syntaxhighlight lang="c++">  
  <syntaxhighlight lang="c++">  
  // CppEXE.cpp
  // CppEXE.cpp

2021年11月22日 (月) 15:23時点における版

概要

C++ EXEからC# DLLの関数を呼び出す方法は、幾つか方法が存在しており、各々にメリットとデメリットがある。
下記の表1に代表的な4種類の方法を示す。

表1. C++ EXEからC# DLLの関数を呼び出す方法

方法 メリット デメリット
C++/CLIを使う 最も簡単
VisualStudioのIntelliSenseも使用可能
プロジェクトの設定で[CLIを使う]に変更する必要がある
C# DLL側で関数をエクスポートする [CLIを使う]に変更しなくてよい
GetProcAddress関数が使用できるため、
よく知られた方法で関数を呼び出す事が出来る
C# DLL側のソースコードが無い場合は利用できない
C# DLL側をCOM 参照可能にする [CLIを使う]に変更しなくてよい C++ EXEのコード量が増えて面倒である
C# DLLに対するC++/CLIの
ラッパープロジェクトを
作成して、C++ EXEから使う
[CLIを使う]に変更しなくてよい
COMを使用しない場合において、
元のプロジェクトの設定を変更したくない場合に使用可能
やり方がスマートではない


上記の表1において、C++/CLIを使う方法とC# DLL側で関数をエクスポートする方法、C++/CLIのラッパープロジェクトを作成する方法を
下記にて紹介する。


C++/CLIを使う方法

 // SampleDLL.cs
 namespace SampleDLL
 {
    public class Class1
    {
       public static int Sum(int a, int b)
       {
          return a + b;
       }
    }
 }

Visual C++のプロジェクト設定を開いて、[共通言語ランタイム サポート (/clr)]に変更する。

 
 // SampleEXE.cpp
 #include <Windows.h>
 #include <iostream>
 
 #using "SampleDLL.dll"
 using namespace SampleDLL;
 
 int main()
 {
    std::cout << Class1::Sum(1, 2) << std::endl;
    return 0;
 }



C# DLL側で関数をエクスポートする方法

まず、プロジェクトを作成してソースコードを記述する。

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


 
 // SampleEXE.cpp
 #include <Windows.h>
 #include <iostream>
 
 typedef int (*Sum)(int a, int b);
 
 int main()
 {
    auto hModule = LoadLibrary(L"DllExportTest.dll");
    auto sum = reinterpret_cast<Sum>(GetProcAddress(hModule, "Sum"));
    std::cout << sum(1, 2) << std::endl;
    return 0;
 }


次に、DllExport.batをダウンロードして、DllExport.batをC# DLLのslnファイルと同じ階層に配置する。

続いて、コマンドプロンプトを開いて以下のコマンドを実行して、.NET DLLExportを起動する。

DllExport.bat -action Configure

.NET DLLExportダイアログにて、[Installed]チェックボックスにチェックを入力して、[Apply]ボタンを押下する。

DotNET DLLExport.png


最後に、C# DLLのプロジェクトをリビルドすると、作成した関数がエクスポートされる。

C++/CLIのラッパープロジェクトを使用する方法

まず、以下に示すソースコードのC# DLLを作成する。

 // CSharpDLL.cs
 namespace CSharpDLL
 {
    public static class CSharpDLLClass
    {
        public static void ShowValue(ref int value)
        {
            DialogResult result = MessageBox.Show("C# Message Box", "C# Message Box", MessageBoxButtons.OKCancel);
            if (result == DialogResult.OK)
            {
               value = 1;
            }
            else
            {
               value = 2;
            }
            return;
        }
    }
 }


次に、以下に示すようなソースコードのC++/CLI DLLを作成する。
その時、ソリューションエクスプローラからC++/CLIプロジェクトを右クリックして[参照の追加]を選択、上記で作成したC# DLLファイルを追加する。

また、Visual C++のプロジェクト設定を開いて、[構成プロパティ] - [全般] - [共通言語ランタイム サポート (/clr)]に変更する。
同様に、[構成プロパティ] - [C/C++] - [プリプロセッサ] - [プリプロセッサの定義]項目に、DLLプリプロセッサを追加する。

 
 // CppCLIDLL.cpp
 #include "stdafx.h"
 #include "CppCLIDLL.h"
 
 using namespace System;
 using namespace System::Reflection;
 using namespace CSharpDLL;
 
 namespace CppCLIDll
 {
    public ref class CppCLIClass
    {
       public:void ShowCSharpMessageBox(int *value)
       {
          CSharpDLLClass::ShowValue(*value);
          return;
       }
    };
 }
 
 void ShowMessageBox(int *value)
 {
    CppCLIDll::CppCLIClass clsCLI;
    clsCLI.ShowCSharpMessageBox(value);
 }


 // CppCLIDLL.h 
 #pragma once
 
 #ifdef DLL
 __declspec(dllexport) void ShowMessageBox(int *value);
 #else
 __declspec(dllimport) void ShowMessageBox(int *value);
 #endif


最後に、以下に示すようなC++のソースコードのプロジェクトを作成する。
その時、メニューバーから[Visual C++のプロジェクト設定]を選択して、[構成プロパティ] - [C/C++] - [全般] - [追加のインクルードディレクトリ]項目に、
CppCLIDLL.hが存在するディレクトリを追加する。

同様に、[構成プロパティ] - [リンカー] - [全般] - [追加のライブラリディレクトリ]項目に、CppCLIDLL.libが存在するディレクトリを追加する。
さらに、[構成プロパティ] - [リンカー] - [入力] - [追加の依存ファイル]項目に、CppCLIDLL.libを追加する。

 
 // CppEXE.cpp
 #include "stdafx.h"
 #include <windows.h>
 #include "TestApp.h"
 #include "CppCLI.h"
  
 int _tmain()
 {
    int result = 0;
 
    ShowMessageBox(&result);
 
    if (result == 1)
    {
       printf("Ok Was Pressed \n");
       printf("%d\n", result);
    }
    else if (result == 2)
    {
       printf("Cancel Was Pressed \n");
       printf("%d\n", result);
    }
    else
    {
       printf("Unknown result \n");
    }
    system("pause");
 
    return 0;
 }



デバッグ

C++プロジェクトからC#プロジェクトに対するデバッグを有効にする手順を記載する。

  1. [ソリューションエクスプローラー]に表示されているC++プロジェクトを右クリックして、[プロパティ]を選択する。
  2. [<プロジェクト名> プロパティページ]画面にて、[構成プロパティ] - [デバッグ]を選択する。
  3. [デバッガーの種類]項目を、[混合]または[自動]に設定して、[OK]ボタンを押下する。