Ⅱ. 関数をエクスポートする方法(P/Invoke)
1. サンプルプログラム
dllexport.def
EXPORTS GetInt GetIntArray GetString GetStruct
MyDll.cpp
#define _CRT_SECURE_NO_WARNINGS #include <Windows.h> int GetInt() { return 123; } void GetIntArray(int x[]) { x[0] = 1; x[1] = 2; x[2] = 3; } void GetString(char *str) { strcpy(str, "あいうえお"); } struct Data { int id; char name[512]; }; void GetStruct(Data *data) { data->id = 1; strcpy(data->name, "名前1"); } BOOL WINAPI DllMain(HINSTANCE hinstModule, DWORD dwReason, LPVOID lpvReserved) { if (dwReason == DLL_PROCESS_ATTACH) { DisableThreadLibraryCalls(hinstModule); } return TRUE; }
Program.cs
struct Data { public int id; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 512)] public string name; } [DllImport("Dll.dll", CallingConvention = CallingConvention.StdCall)] static extern int GetInt(); [DllImport("Dll.dll", CallingConvention = CallingConvention.StdCall)] static extern void GetIntArray([Out, MarshalAs(UnmanagedType.LPArray)] int[] data); [DllImport("Dll.dll", CallingConvention = CallingConvention.StdCall)] static extern void GetString(StringBuilder str); [DllImport("Dll.dll", CallingConvention = CallingConvention.StdCall)] static extern void GetStruct(ref Data data); static void Main(string[] args) { // int Console.WriteLine(GetInt()); // int配列 var intArray = new int[3]; GetIntArray(intArray); Console.WriteLine(string.Join(",", intArray)); // string var sb = new StringBuilder(); GetString(sb); Console.WriteLine(sb); // 構造体 var data = new Data(); GetStruct(ref data); Console.WriteLine($"{data.id},{data.name}"); }
2. 実行結果
3. DllImportの呼出規約について
C#側のDllImportの呼出規約はデフォルトでCallingConvention.StdCallになります。
C++側の関数の呼出規約はデフォルトで__cdeclです。
スタック処理が異なる為不具合が発生する場合があります。
明示的に指定する事を心がけたほうが良いです。
※呼出規約とは
https://kagasu.hatenablog.com/entry/2017/12/18/213255
Ⅲ. C++/CLIを利用する方法
1. サンプルプログラム
Source.cpp
namespace TestDll { public ref class MyClass { public: static int Sum(int a, int b) { return a + b; } }; }
Program.cs
using System; namespace Test { class Program { static void Main(string[] args) { var result = TestDll.MyClass.Sum(1, 2); Console.WriteLine($"Result = {result}"); } } }
2. 実行結果
Result = 3