逆P/Invokeを駆使してTTBaseのプラグインを作れるか?

TTBase http://ttbase.sourceforge.jp/

逆P/Invoke http://www.artonx.org/diary/20081124.html#p01

これでC#でTTBaseのプラグイン作れるんじゃね?と思った。

TTBase.cs TTBaseで使用する構造体とか定数とか

 

using System;
using System.Runtime.InteropServices;
namespace TTBasePlugInTest {
    //プラグインのロードタイプ
    public enum LoadType {
        ptAlwayLoad = 0,
        ptLoadAtUse = 1,
        ptSpecViolation = 0xFFFF
    }
    //メニューに関する定数
    public enum Menu {
        dmNone = 0,
        dmSystemMenu = 1,
        dmToolMenu = 2,
        dmHotKeyMenu = 4,
        dmMenuChecked = 8
    }
    public enum LogOut {
        elNever = 0,
        elError = 1,
        elWarning = 2,
        elInfo = 3,
        elDebug = 4
    }
    [StructLayout(LayoutKind.Sequential,CharSet = CharSet.Ansi)]
    public struct PLUGIN_COMMAND_INFO {
        [MarshalAs(UnmanagedType.LPStr)]
        public string Name;
        [MarshalAs(UnmanagedType.LPStr)]
        public string Caption;
        public int CommandID;
        public int Attr;
        public int ResID;
        public int DispMenu;
        public uint TimerInterval;
        public uint TimerCounter;
    }
    [StructLayout(LayoutKind.Sequential,CharSet= CharSet.Ansi)]
    public struct PLUGIN_INFO {
        public ushort NeedVersion;
        [MarshalAs(UnmanagedType.LPStr)]
        public string Name;
        [MarshalAs(UnmanagedType.LPStr)]
        public string FileName;
        public ushort PluginType;
        public uint VersionMS;
        public uint VersionLS;
        public uint CommandCount;
        [MarshalAs(UnmanagedType.LPStruct)]
        public IntPtr Commands;
        //public PLUGIN_COMMAND_INFO Commands;
        public uint LoadTime;
    }
}

 

Class1.cs TTBaseに公開するメソッドを実装

 

using System;
using System.Runtime.InteropServices;
namespace TTBasePlugInTest {
    public class Class1 {
        public static IntPtr TTBEVent_InitPluginInfo(string PluginFilename) {
            PLUGIN_INFO r = new PLUGIN_INFO();
            r.FileName = PluginFilename;
            r.NeedVersion = 0;
            r.Name = "テスト";
            r.PluginType = (int)LoadType.ptAlwayLoad;
            r.CommandCount = 1;
            PLUGIN_COMMAND_INFO pci = new PLUGIN_COMMAND_INFO();
            pci.Name = "test";
            pci.Caption = "てすてす、テストのテストです";
            pci.CommandID = 0;
            pci.DispMenu = (int)(Menu.dmToolMenu | Menu.dmHotKeyMenu);
            IntPtr pciPtr = Marshal.AllocHGlobal(Marshal.SizeOf(pci));
            Marshal.StructureToPtr(pci, pciPtr, false);
            r.Commands = pciPtr;
            //r.Commands = pci;
            IntPtr iPtr = Marshal.AllocHGlobal(Marshal.SizeOf(r));
            Marshal.StructureToPtr(r, iPtr, false);
            return iPtr;
        }
        public static void TTBEvent_FreePluginInfo(IntPtr PluginInfo) {
            Marshal.FreeHGlobal(PluginInfo);
        }
        public static int TTBEvent_Init(string PluginFilename, int hPlugin) {
            return 1;
        }
        public static void TTBEvent_Unload() {
        }
        static int i;
        public static int TTBEvent_Execute(int CommandID, IntPtr hWnd) {
            i++;
            System.Windows.Forms.MessageBox.Show(i.ToString());
            return 1;
        }
        public static void TTBEvent_WindowsHook(int Msg, int wParam, int lParam) {
        }
    }
}

 

上のコードをビルドしたら

 

D:\My Documents\Visual Studio 2008\Projects\TTBasePlugInTest\TTBasePlugInTest\bi
n\Release>ildasm /OUT=TTBasePlugInTest.il TTBasePlugInTest.dll

 

でILにする。

逆P/Invokeを参考にILを編集

 

D:\My Documents\Visual Studio 2008\Projects\TTBasePlugInTest\TTBasePlugInTest\bi
n\Release>c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\ilasm.exe /DLL TTBasePlu
gInTest.il
Microsoft (R) .NET Framework IL Assembler.  Version 2.0.50727.3053
Copyright (c) Microsoft Corporation.  All rights reserved.
Assembling 'TTBasePlugInTest.il'  to DLL --> 'TTBasePlugInTest.dll'
Source file is ANSI
Assembled method TTBasePlugInTest.Class1::TTBEVent_InitPluginInfo
Assembled method TTBasePlugInTest.Class1::TTBEvent_FreePluginInfo
Assembled method TTBasePlugInTest.Class1::TTBEvent_Init
Assembled method TTBasePlugInTest.Class1::TTBEvent_Unload
Assembled method TTBasePlugInTest.Class1::TTBEvent_Execute
Assembled method TTBasePlugInTest.Class1::TTBEvent_WindowsHook
Assembled method TTBasePlugInTest.Class1::.ctor
Creating PE file
Emitting classes:
Class 1:        TTBasePlugInTest.Class1
Class 2:        TTBasePlugInTest.PLUGIN_INFO
Class 3:        TTBasePlugInTest.PLUGIN_COMMAND_INFO
Class 4:        TTBasePlugInTest.LoadType
Class 5:        TTBasePlugInTest.Menu
Class 6:        TTBasePlugInTest.LogOut
Emitting fields and methods:
Global
Class 1 Fields: 1;      Methods: 7;
Class 2 Fields: 9;
Class 3 Fields: 8;
Class 4 Fields: 4;
Class 5 Fields: 6;
Class 6 Fields: 6;
Resolving local member refs: 13 -> 13 defs, 0 refs, 0 unresolved
Emitting events and properties:
Global
Class 1
Class 2
Class 3
Class 4
Class 5
Class 6
Resolving local member refs: 0 -> 0 defs, 0 refs, 0 unresolved
Writing PE file
Operation completed successfully

 

とILからDLLを作成。メッセージの意味はよくわからないけど、多分成功してる。

これで出来たDLLをTTBaseのディレクトリにコピーしてTTBaseを起動するも…プラグインとして認識されない。

どこが上手く行ってないのかもわからない状態。

http://twitter.com/takeshik/statuses/2419234928

とか言われたけどC++/CLIとかキモいし。

http://twitter.com/takeshik/statuses/2419254967

とか突っ込まれたけどその通りだと思う。

C#でやることに意味があるのですよ。C#可愛いよ、C#可愛い。

でもC#で出来て無いから何の意味も無いという…。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください