diff --git a/TTTConsole/Plugin.cs b/TTTConsole/Plugin.cs new file mode 100644 index 0000000..ba01a07 --- /dev/null +++ b/TTTConsole/Plugin.cs @@ -0,0 +1,74 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Runtime.InteropServices; + +namespace TTT { + + class Plugin { + + // DLLの動的読み込みに必要なWin32API関数 + [DllImport("kernel32.dll", SetLastError = true)] + public static extern IntPtr LoadLibrary(string lib); + [DllImport("kernel32.dll", SetLastError = true)] + public static extern void FreeLibrary(IntPtr module); + [DllImport("kernel32.dll", SetLastError = true)] + public static extern IntPtr GetProcAddress(IntPtr module, string proc); + + private delegate void GetNameDelegate(StringBuilder s, Int32 bufsize); + private delegate bool IsHumanDelegate(); + public delegate int MyTurnDelegate(IntPtr board); + public string Name { get; private set; } + public bool IsHuman { get; private set; } + public MyTurnDelegate MyTurn { get; private set; } + + private IntPtr _module; + + /// + /// コンストラクタ + /// + public Plugin() { + _module = IntPtr.Zero; + } + + /// + /// デストラクタ + /// + ~Plugin() { + if (_module != IntPtr.Zero) FreeLibrary(_module); + } + + /// + /// プラグインの読み込み + /// + /// プラグインDLLファイル名 + /// 読み込みの成否 + public bool Load(string filename) { + var module = LoadLibrary(filename); + if (module == IntPtr.Zero) return false; + + // 名前の取得 + IntPtr method = GetProcAddress(module, "GetName"); + if (method == IntPtr.Zero) return false; + var GetName = (GetNameDelegate)Marshal.GetDelegateForFunctionPointer(method, typeof(GetNameDelegate)); + System.Text.StringBuilder sb = new System.Text.StringBuilder(256); + GetName(sb, sb.Capacity); + Name = sb.ToString(); + + // 人間かどうかの取得 + method = GetProcAddress(module, "IsHuman"); + if (method == IntPtr.Zero) return false; + var isHumanFunc = (IsHumanDelegate)Marshal.GetDelegateForFunctionPointer(method, typeof(IsHumanDelegate)); + IsHuman = isHumanFunc(); + + // 思考関数ポインタの取得 + method = GetProcAddress(module, "MyTurn"); + if (method == IntPtr.Zero) return false; + MyTurn = (MyTurnDelegate)Marshal.GetDelegateForFunctionPointer(method, typeof(MyTurnDelegate)); + + return true; + } + } +} diff --git a/TTTConsole/Program.cs b/TTTConsole/Program.cs index 597acd0..f4e5264 100644 --- a/TTTConsole/Program.cs +++ b/TTTConsole/Program.cs @@ -3,28 +3,16 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -using System.Runtime.InteropServices; using TTT; namespace TTTConsole { class Program { - [DllImport("kernel32.dll", SetLastError = true)] - public static extern IntPtr LoadLibrary(string lib); - [DllImport("kernel32.dll", SetLastError = true)] - public static extern void FreeLibrary(IntPtr module); - [DllImport("kernel32.dll", SetLastError = true)] - public static extern IntPtr GetProcAddress(IntPtr module, string proc); - - private delegate void GetNameDelegate(StringBuilder s, Int32 bufsize); - private delegate bool IsHumanDelegate(); - private delegate int MyTurnDelegate(IntPtr board); - static string[] PLAYER_STR = new string[] { "", "先手", "後手" }; static string[] PLAYER_MARK = new string[] { " ", "○", "×" }; - static List names = new List(); static int[] thinkers; + static List plugins; static bool showNumber = false; /// @@ -41,68 +29,25 @@ // プラグインDLLを開く var pluginFiles = new List() { "TPIHuman.dll", "TPIRandom.dll" }; - var modules = new List(); - var GetName = new List(); - var IsHuman = new List(); - var MyTurn = new List(); - + plugins = new List(); foreach (var file in pluginFiles) { - var module = LoadLibrary(file); - if (module == IntPtr.Zero) // error handling - { - Console.WriteLine($"Could not load library: {Marshal.GetLastWin32Error()}"); - continue; - } - - IntPtr method = GetProcAddress(module, "GetName"); - if (method == IntPtr.Zero) // error handling - { - Console.WriteLine($"Could not load 'GetName' method: {Marshal.GetLastWin32Error()}"); - FreeLibrary(module); // unload library - continue; - } - GetName.Add((GetNameDelegate)Marshal.GetDelegateForFunctionPointer(method, typeof(GetNameDelegate))); - - method = GetProcAddress(module, "IsHuman"); - if (method == IntPtr.Zero) // error handling - { - Console.WriteLine($"Could not load 'IsHuman' method: {Marshal.GetLastWin32Error()}"); - FreeLibrary(module); // unload library - continue; - } - IsHuman.Add((IsHumanDelegate)Marshal.GetDelegateForFunctionPointer(method, typeof(IsHumanDelegate))); - - method = GetProcAddress(module, "MyTurn"); - if (method == IntPtr.Zero) // error handling - { - Console.WriteLine($"Could not load 'MyTurn' method: {Marshal.GetLastWin32Error()}"); - FreeLibrary(module); // unload library - continue; - } - MyTurn.Add((MyTurnDelegate)Marshal.GetDelegateForFunctionPointer(method, typeof(MyTurnDelegate))); - - modules.Add(module); - } - - // プラグイン名の取得 - System.Text.StringBuilder sb = new System.Text.StringBuilder(256); - foreach (var gn in GetName) { - gn(sb, sb.Capacity); - names.Add(sb.ToString()); + var plugin = new Plugin(); + if (!plugin.Load(file)) continue; + plugins.Add(plugin); } // プレイヤーの選択 Console.WriteLine("プレイヤーの選択"); thinkers = new int[ttt.PLAYERS]; for (var pl=0; pl< ttt.PLAYERS; pl++) { - for (var i = 0; i < names.Count; i++) { - Console.WriteLine($"({i + 1}) {names[i]}"); + for (var i = 0; i < plugins.Count; i++) { + Console.WriteLine($"({i + 1}) {plugins[i].Name}"); } Console.Write($"{PLAYER_STR[pl + 1]} を選んでください: "); var input = Console.ReadLine(); if (!int.TryParse(input, out thinkers[pl])) return; - if (thinkers[pl] < 1 || thinkers[pl] > names.Count) return; + if (thinkers[pl] < 1 || thinkers[pl] > plugins.Count) return; --thinkers[pl]; } @@ -117,9 +62,9 @@ ShowBoard(ttt); Console.Write($"{PlayerStr(ttt.Player)} の番"); - if (IsHuman[thinkers[(int)ttt.Player - 1]]()) Console.WriteLine(""); - ttt.Set(MyTurn[thinkers[(int)ttt.Player - 1]](ttt.GetBoard())); - if (IsHuman[thinkers[(int)ttt.Player - 1]]()) Console.WriteLine($" --> {ttt.LastSet + 1}"); + if (plugins[thinkers[(int)ttt.Player - 1]].IsHuman) Console.WriteLine(""); + ttt.Set(plugins[thinkers[(int)ttt.Player - 1]].MyTurn(ttt.GetBoard())); + if (!plugins[thinkers[(int)ttt.Player - 1]].IsHuman) Console.WriteLine($" --> {ttt.LastSet + 1}"); } while (ttt.Judge == JUDGE.None); @@ -147,7 +92,6 @@ // 終了 Console.Write("Press [Enter] to exit."); Console.ReadLine(); - foreach (var module in modules) FreeLibrary(module); } /// @@ -183,7 +127,7 @@ /// プレイヤー /// 表示文字列 static string PlayerStr(PLAYER p) { - return $"{PLAYER_STR[(int)p]}({names[thinkers[(int)p - 1]]})"; + return $"{PLAYER_STR[(int)p]}({plugins[thinkers[(int)p - 1]].Name})"; } } } diff --git a/TTTConsole/TTTConsole.csproj b/TTTConsole/TTTConsole.csproj index fd608e5..4b4bf99 100644 --- a/TTTConsole/TTTConsole.csproj +++ b/TTTConsole/TTTConsole.csproj @@ -63,6 +63,7 @@ +