Newer
Older
TicTacToe / TTTConsole / Plugin.cs
using System;
using System.Runtime.InteropServices;
using System.Text;

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;

        /// <summary>
        /// コンストラクタ
        /// </summary>
        public Plugin() {
            _module = IntPtr.Zero;
        }

        /// <summary>
        /// デストラクタ
        /// </summary>
        ~Plugin() {
            if (_module != IntPtr.Zero) FreeLibrary(_module);
        }

        /// <summary>
        /// プラグインの読み込み
        /// </summary>
        /// <param name="filename">プラグインDLLファイル名</param>
        /// <returns>読み込みの成否</returns>
        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;
        }
    }
}