C++のdllをC#で呼び出し方法とは?Visual Studio 2019での事前準備から紹介!
- システム
エンジニア - C++のdllをC#で呼び出し方法を教えてください。
- プロジェクト
マネージャー - C++のdllをC#で呼び出し方法や事前準備などについて紹介します。
C++のdllをC#で呼び出しとは?
C#でC++のdllの呼び出しを紹介します。
過去にC++で作成した関数をC#で使いたい場合、C++の関数をdll(ダイナミックリンクライブラリ)にしてC#でそれを呼び出すことが可能です。
これを行うにはちょっとしたテクニックが必要になります。それをVisual Studio 2019を使って説明します。
C++のdllをC#で呼び出しをするにはマーシャリングの処理が必要
そもそもC++とC#はシステムが異なります。そこで異なるシステム間でデータを交換できるようにするための処理、つまり、マーシャリングの処理が必要です。
単純にC++のdllをC#で呼び出すことはできません。それはC#とC++のメモリへの配置が基本型以外では異なっているためです。しかし、マーシャリングの処理を行えばC#でC++のdllの呼び出しが可能になるのです。
Visual Studio 2019での事前準備
C#でC++のdllの呼び出しを行うためにVisual Studio 2019での事前準備に取りかかりましょう。Visual Studio 2019を起動させたら、まず、C#の.NET Frameworkのコンソールアプリケーションを選択し、それをここでは「ConsoleApp1」と名付けます。
次に呼び出しに使うC++のdll作成です。右の「ソリューションエクスプローラー」の「ソリューション」を右クリックしてそこで現われる「追加」の中の「新しいプロジェクト」を選択した後、C++のダイナミックライブラリ(.dll)を選択し「CPlusDLL」と名付けます。これで呼び出しに使うdllの作成準備完了です。
コードを書く
それではコードを書いていきます。
・ヘッダーファイル
・C++の関数
・C#のソースコード
・Visual Studio 2019の設定
・デバッグ
この順番で進めていきます。
C++のヘッダーファイル
「ソリューションエクスプローラー」の「CPlusDLL」を右クリックして「追加」の「新しい項目」を選択し、その中から「ヘッダーファイル」を選び、「dellExport.h」と名付けます。
ソースコードは次の通りです。
1
2
3
4
5
6
7
8
9
|
#pragma once
#ifdef __cplusplus
#define DLLEXPORT extern "C" __declspec(dllexport)
#else
#define DLLEXPORT __declspec(dllexport)
#endif
using namespace std;
|
なお、
1
|
using namespace std;
|
をヘッダーファィルに書き込んでいます。
C++のソースコード
C++のソースコードを見てみましょう。「ソリューションエクスプローラー」の「CPlus」を右クリックして「追加」の「新しい項目」で「C++ソースコード(.cpp)」を選択。「CPlus.cpp」と名付けます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
#include <string>
#include "dellExport.h"
static string _str = "";
static wstring _wstr = L"";
DLLEXPORT int __stdcall multiply(int x, int y)
{
return 2*x + 3*y;
}
DLLEXPORT void __stdcall multiplyUsePointer(int *x, int *y, int *result)
{
*result = 2*(*x) + 3*(*y);
}
DLLEXPORT void __stdcall setNameString(const char *str)
{
_str = string(str);
}
DLLEXPORT const char *__stdcall getNameString()
{
return _str.c_str();
}
DLLEXPORT void __stdcall setNameWString(const wchar_t *str)
{
_wstr = wstring(str);
}
DLLEXPORT const wchar_t *__stdcall getNameWString()
{
return _wstr.c_str();
}
|
C#のコード
C#のソースコードです。「ConsoleApp1」で自動生成された「Program.cs」にソースコードを書き、C++のdllの呼び出しを行います。第一の方法としてDllImport関数の第一引数に呼び出しされるCPlusDLL.dllの絶対パスのソースコードを紹介します。後に、絶対パスを書かない方法を紹介します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
|
using System;
using System.Runtime.InteropServices;
namespace ConsoleApp1
{
class Program
{
[DllImport("C:\\path\\to\\ConsoleApp1\\x64\\Debug\\CPlusDLL.dll", EntryPoint = "multiply")]
static extern int _multiply(int x, int y);
[DllImport("C:\\path\\to\\ConsoleApp1\\x64\\Debug\\CPlusDLL.dll", EntryPoint = "multiplyUsePointer")]
static extern void _multiplyUsePointer(ref int x, ref int y, out int result);
[DllImport("C:\\path\\to\\ConsoleApp1\\x64\\Debug\\CPlusDLL.dll", EntryPoint = "setNameString", CharSet = CharSet.Ansi)]
static extern void _setNameString(string t);
[DllImport("C:\\path\\to\\ConsoleApp1\\x64\\Debug\\CPlusDLL.dll", EntryPoint = "getNameString", CharSet = CharSet.Ansi)]
static extern IntPtr _getNameString();
[DllImport("C:\\path\\to\\ConsoleApp1\\x64\\Debug\\CPlusDLL.dll", EntryPoint = "setNameWString", CharSet = CharSet.Unicode)]
static extern void _setNameWString(string t);
[DllImport("C:\\path\\to\\ConsoleApp1\\x64\\Debug\\CPlusDLL.dll", EntryPoint = "getNameWString", CharSet = CharSet.Unicode)]
static extern IntPtr _getNameWString();
static void Main(string[] args)
{
int x = 100;
int y = 500;
int resultMultiply = _multiply(x, y);
Console.WriteLine("multiply = " + resultMultiply);
_multiplyUsePointer(ref x, ref y, out int resultMultiplyUsePointer);
Console.WriteLine("multiplyUsePointer = " + resultMultiplyUsePointer);
string testString = "東京都中央区大手町1-1-1";
_setNameString(testString);
Console.WriteLine("getNameString = " + Marshal.PtrToStringAnsi(_getNameString()));
_setNameWString(testString);
Console.WriteLine("getNameWString = " + Marshal.PtrToStringUni(_getNameWString()));
#if DEBUG
Console.WriteLine("続行するには何かキーを押してください...");
Console.ReadKey();
#endif
}
}
}
|
絶対パスを指定する方法
第一の方法としてDllImport関数の第一引数でCPlusDLL.dllへは絶対パスで指定しなければいけません。\\path\\to\\となっているのは各人の設定環境に合わせて下さい。
プロパティを編集する方法
DllImprt関数の第一引数にどうしても絶対パスを指定したくないという場合は「ソリューションエクスプローラー」の「CPlusDLL」を右クリックして、プロパティを選択します。「全般」の中で、「出力ディレクトリ」を編集します。左上で「アクティブ(Debug)」を選択した場合は「出力ディレクトリ」の「編集」をクリックして「$(SolutionDir)bin\Debug」に編集します。
次に左上で「Release」を選択し、「出力ディレクトリ」を「$(SolutionDir)bin\Release\」に編集します。
プロパティを編集したときのコード
プロパティを編集したら、Program.csのソースコードは次の通りです。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
|
using System;
using System.Runtime.InteropServices;
namespace ConsoleApp1
{
class Program
{
[DllImport("CPlusDLL.dll", EntryPoint = "multiply")]
static extern int _multiply(int x, int y);
[DllImport("CPlusDLL.dll", EntryPoint = "multiplyUsePointer")]
static extern void _multiplyUsePointer(ref int x, ref int y, out int result);
[DllImport("CPlusDLL.dll", EntryPoint = "setNameString", CharSet = CharSet.Ansi)]
static extern void _setNameString(string t);
[DllImport("CPlusDLL.dll", EntryPoint = "getNameString", CharSet = CharSet.Ansi)]
static extern IntPtr _getNameString();
[DllImport("CPlusDLL.dll", EntryPoint = "setNameWString", CharSet = CharSet.Unicode)]
static extern void _setNameWString(string t);
[DllImport("CPlusDLL.dll", EntryPoint = "getNameWString", CharSet = CharSet.Unicode)]
static extern IntPtr _getNameWString();
static void Main(string[] args)
{
int x = 100;
int y = 500;
int resultMultiply = _multiply(x, y);
Console.WriteLine("multiply = " + resultMultiply);
_multiplyUsePointer(ref x, ref y, out int resultMultiplyUsePointer);
Console.WriteLine("multiplyUsePointer = " + resultMultiplyUsePointer);
string testString = "東京都中央区大手町1-1-1";
_setNameString(testString);
Console.WriteLine("getNameString = " + Marshal.PtrToStringAnsi(_getNameString()));
_setNameWString(testString);
Console.WriteLine("getNameWString = " + Marshal.PtrToStringUni(_getNameWString()));
#if DEBUG
Console.WriteLine("続行するには何かキーを押してください...");
Console.ReadKey();
#endif
}
}
}
|
バッチビルド
ビルドを行う前にすることがあります。Visual Studio 2019の「ビルド」をクリックし、「バッチビルド」を選択します。「ビルド」のチェックボックスで、「ConsoleApp1」は全てチェックを入れ、「CPlusDLL」は「x64」にのみチェックを入れます。そして「ビルド」を行うと、エラーなしに正常終了するはずです。
デバッグ
Visual Studio 2019の上部真ん中にある「開始」をクリックしてデバッグを行います。きちんとCPlusDLL.dllを呼び出ししていれば、コマンドプロンプトが立ち上がり、次のように表示されれば成功です。
1
2
3
4
5
|
multiply = 1700
multiplyUsePointer = 1700
getNameString = 東京都中央区大手町1-1-1
getNameWString = 東京都中央区大手町1-1-1
続行するには何かキーを押してください...
|
C++で定義した関数が行われきちんとCPlusDLL.dllの呼び出しが行われていることが分かります。
- システム
エンジニア - C++のdllをC#で呼び出し方法やコードの書き方がわかりました。
- プロジェクト
マネージャー - 今回紹介した方法を参考に、実際にコードを書いて理解を深めましょう。
C++のdllをC#で呼び出し
システムの違うC++のdllをC#で呼び出しすることの例を紹介しました。
・Visual Studio 2019の設定
・ソースコード
・デバッグ
以上でC#でC++のdllの呼び出しに成功しました。興味のある方は自分でソースコードを書いて実際に行ってみて下さい。
FEnet.NETナビ・.NETコラムは株式会社オープンアップシステムが運営しています。
株式会社オープンアップシステムはこんな会社です
秋葉原オフィスには株式会社オープンアップシステムをはじめグループのIT企業が集結!
数多くのエンジニアが集まります。
-
スマホアプリから業務系システムまで
スマホアプリから業務系システムまで開発案件多数。システムエンジニア・プログラマーとしての多彩なキャリアパスがあります。
-
充実した研修制度
毎年、IT技術のトレンドや社員の要望に合わせて、カリキュラムを刷新し展開しています。社内講師の丁寧なサポートを受けながら、自分のペースで学ぶことができます。
-
資格取得を応援
スキルアップしたい社員を応援するために資格取得一時金制度を設けています。受験料(実費)と合わせて資格レベルに合わせた最大10万円の一時金も支給しています。
-
東証プライム上場企業グループ
オープンアップシステムは東証プライム上場「株式会社オープンアップグループ」のグループ企業です。
安定した経営基盤とグループ間のスムーズな連携でコロナ禍でも安定した雇用を実現させています。
株式会社オープンアップシステムに興味を持った方へ
株式会社オープンアップシステムでは、開発系エンジニア・プログラマを募集しています。
年収をアップしたい!スキルアップしたい!大手の上流案件にチャレンジしたい!
まずは話だけでも聞いてみたい場合もOK。お気軽にご登録ください。
Array新着案件New Job
-
開発エンジニア/東京都品川区/【WEB面談可】/在宅ワーク
月給29万~30万円東京都品川区(大崎駅) -
遠隔テストサービス機能改修/JavaScript/東京都港区/【WEB面談可】/テレワーク
月給45万~60万円東京都港区(六本木駅) -
病院内システムの不具合対応、保守/東京都豊島区/【WEB面談可】/テレワーク
月給30万~30万円東京都豊島区(池袋駅) -
開発/JavaScript/東京都豊島区/【WEB面談可】/テレワーク
月給50万~50万円東京都豊島区(大塚駅) -
債権債務システム追加開発/東京都文京区/【WEB面談可】/在宅勤務
月給62万~67万円東京都文京区(後楽園駅) -
PMO/東京都豊島区/【WEB面談可】/在宅勤務
月給55万~55万円東京都豊島区(池袋駅)